diff --git a/.classpath b/.classpath deleted file mode 100644 index 2454c8f20..000000000 --- a/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.gitignore b/.gitignore index db505a540..166f02d0c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ bin/ target node_modules _site +buc.sso*.jar +out +.idea +*.iml diff --git a/.project b/.project deleted file mode 100644 index 864cf9274..000000000 --- a/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - RAP - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - com.genuitec.eclipse.ast.deploy.core.DeploymentBuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - com.genuitec.eclipse.ast.deploy.core.deploymentnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.jdt.core.javanature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope deleted file mode 100644 index 49b9981e4..000000000 --- a/.settings/.jsdtscope +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.settings/com.genuitec.eclipse.j2eedt.core.prefs b/.settings/com.genuitec.eclipse.j2eedt.core.prefs deleted file mode 100644 index e6772cc4c..000000000 --- a/.settings/com.genuitec.eclipse.j2eedt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Tue Dec 24 13:46:52 CST 2013 -defaultTldInfo=f\=http\://java.sun.com/jsf/core;http\://java.sun.com/jsf/html\=h;http\://struts.apache.org/tags-bean\=bean;http\://java.sun.com/jsp/jstl/fmt\=fmt;bean\=http\://struts.apache.org/tags-bean;nested\=http\://struts.apache.org/tags-nested;http\://java.sun.com/jsp/jstl/sql\=sql;fmt\=http\://java.sun.com/jsp/jstl/fmt;c\=http\://java.sun.com/jsp/jstl/core;http\://struts.apache.org/tags-logic\=logic;http\://java.sun.com/jsp/jstl/xml\=x;http\://java.sun.com/jsp/jstl/core\=c;logic\=http\://struts.apache.org/tags-logic;h\=http\://java.sun.com/jsf/html;http\://struts.apache.org/tags-tiles\=tiles;http\://java.sun.com/jsp/jstl/functions\=fn;tiles\=http\://struts.apache.org/tags-tiles;sql\=http\://java.sun.com/jsp/jstl/sql;http\://struts.apache.org/tags-html\=html;html\=http\://struts.apache.org/tags-html;http\://struts.apache.org/tags-nested\=nested;http\://java.sun.com/jsf/core\=f;fn\=http\://java.sun.com/jsp/jstl/functions;x\=http\://java.sun.com/jsp/jstl/xml -eclipse.preferences.version=1 -useAssemblyMapping=true diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 5cf2c6b09..000000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Wed Apr 09 10:53:37 CST 2014 -eclipse.preferences.version=1 -encoding//WebContent/tcom/const.inc.vm=UTF-8 -encoding//src/database/test-data.sql=UTF-8 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 08b9d7437..000000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -#Thu Dec 12 15:44:46 CST 2013 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index 7a46530f6..000000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Thu Dec 12 15:44:43 CST 2013 -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 7cdbb139d..000000000 --- a/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 5c227556d..000000000 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a48..000000000 --- a/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6e..000000000 --- a/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/.settings/org.eclipse.wst.ws.service.policy.prefs b/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index a2cc26e2d..000000000 --- a/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Thu Aug 05 13:37:25 CST 2010 -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/DATABASE_CHANGE.md b/DATABASE_CHANGE.md new file mode 100644 index 000000000..0042b199a --- /dev/null +++ b/DATABASE_CHANGE.md @@ -0,0 +1,29 @@ +### Database Change v0.11.1 +1. 增加了tb_module.name的长度,防止过长模块名报错 +2. 增加tb_action.disable_cache字段用于自动化禁用cache处理 + +```sql +ALTER TABLE `rap_db`.`tb_module` CHANGE COLUMN `name` `name` VARCHAR(128) NOT NULL ; +ALTER TABLE `rap_db`.`tb_action` ADD COLUMN disable_cache TINYINT NOT NULL DEFAULT 0; +``` + + + +### Database Change v0.11.0 + +add mock count Oct.15 2014 +增加了MOCK调用次数记录 2014-10-15 + +```sql +ALTER TABLE tb_project +ADD COLUMN mock_num int(10) NOT NULL + DEFAULT 0 +``` + +add employee id Oct.1 2014 +增加员工ID 2014-10-1 + +```sql +ALTER TABLE tb_user + ADD emp_id varchar(128) NULL +``` \ No newline at end of file diff --git a/INTRO.md b/INTRO.md deleted file mode 100644 index 04812b825..000000000 --- a/INTRO.md +++ /dev/null @@ -1,88 +0,0 @@ -RAP v0.8 介绍 -=== - -你和你的小伙伴们还在用纯手工的方式小心翼翼的编写和维护接口文档么? - -你和你的小伙伴们还在手动的一条一条伪造自测数据么? - -你和你的小伙伴们还在联调时因接口格式不对而浪费大量宝贵时间么? - -如果是,RAP或许能够让你体验一次“鸟枪换炮”的快感。 - -## 概述 ## - -在前后端分离的WEB开发模式中,通常需定义接口文档来规范其接口形式,如接口地址、参数、类型、含义等。RAP 致力于提供方便的可视化工具录入并维护这些文档,并通过分析这些文档数据,重复利用,生成自测数据、校验真实数据,提升开发效率。 - -接口管理工作由来已久,传统管理方式无论用Word、Wiki或更高级的工具,最常遇到的问题是:“接口文档不全,更新不及时”。由于开发过程中持续的接口调整几乎无可避免,一旦接口文档不能及时同步,一切都是空谈!RAP工具改变了这一现状,任何接口的变化需要通过更新RAP内的接口文档来反馈给前端,而RAP通过接口规则生成的模拟数据则构成了整个前端开发环境的基础。因此,接口文档的全面性、实时性和正确性成为前后端开发过程中的强依赖,同时这也构成了RAP服务于后端单元测试和UI自动化测试的基石。在RAP成为前端开发过程的必经环节之后,这对RAP解决复杂response数据的结构化描述、 版本历史管理、 接口维护工具、易用性等问题时提出了更高的要求。 - -## 用户场景 ## - -RAP的主要目标用户群有四种: -- 前端,使用RAP制定接口,生成自测数据。 -- 后端,使用RAP制定接口,校验真实输出的格式。 -- 测试,使用RAP录制Mock规则,实现自动化测试。 -- 其它,各种角色,需要了解该系统接口情况的人。 - -## 使用数据 ## - -截至发稿时,目前RAP已为`112`名工程师提供服务,立项`49`个,定义了`445`个接口,完成了`上万`次动态数据MOCK。 - -## 解决的问题 ## - -### 一、接口编辑的便利性 ### - -RAP所解决的问题,主要集中于中大型的企业级项目,接口形式有一定的复杂度。比如一个报表的请求,可能嵌套较多的层级。传统的方式描述较多嵌套的层级结构会较为麻烦,复制、移动等修改都消耗大量时间,而RAP通过GUI工具和结构分析可以很好的解决这些问题。再复杂的嵌套参数,一键复制和移动。展开、折叠毫不费力。RAP专为接口编辑而设计,在用户体验和细节上做了大量处理,保证高效、方便的接口文档编辑。 - -RAP文档编辑区 - -### 二、手写模拟数据耗费时间 ### - -从设计阶段之后到联调之前,前端需要编写大量的自测数据来自测(尤其层级嵌套或CASE较多的情况会比较麻烦)。有了RAP告别手写自测数据,RAP会根据最新的接口文档动态实时的产生模拟数据,且结合MockJS支持深度定制的数据模拟规则。“一处写好,大家共享。”不管是自测、做DEMO,RAP在数据模拟上都可用最少时间,达到最大产出。对于前端,RAP模拟请求返回生成靠谱的自测数据,对于后端,RAP根据接口文档中定义的参数格式伪造实际请求以此测试后端实际接口的准确性。 - -### 三、有规范却不执行 ### - -这是实际常见到的问题,定义好了接口,联调的时候发现实际数据不符合规则或前端手写的自测数据错误导致前端未正确处理。RAP MOCK保证前端代码对接口正确的处理,同时,RAP会根据接口文档中的结构动态验证后端实际返回的正确性,在联调前扫清所有后端格式错误。 - -### 四、文档维护 & 实时性 ### - -传统的接口文档若不进行持续的维护,将会逐渐失效。没有实时性的文档很快将会变成废品,RAP集中式的文档编辑,实时生效的前后端工具将RAP中的接口文档变成强依赖。RAP中的接口文档一旦修改,所有的自动化功能都将受其影响,反之也保证了RAP中的文档始终是最新的。 - -## 特点介绍 ## - -### 一、方便快捷的创建、共享文档 ### - -RAP中对接口文档的编辑提供了一套可视化界面,编辑操作像Excel一样方便简单。比如您可以展开、收缩层级嵌套的参数结构,查看、切换不同历史版本,一键复制、移动参数(包括层级嵌套的复杂参数)。为方便离线查看,您也可以导出接口文档(Word文档)。在即将问世的v1.0新版RAP中,我们还会增加: -注入规范验证(强制接口命名规范)、接口模板等提升文档易用性的功能。 -针对RD、FE、QA不同的角色提供不同的视图及功能。比如后端更关注接口地址,前端更关心业务逻辑中划分的”页面“或”模块“。我们将持续提升产品易用性。RAP的核心是接口文档,因此文档编辑的用户体验是我们非常重视的,有了较好的文档编辑用户体验,用户才愿意用RAP去维护文档,并充分利用这些结构化的数据将更多工作自动化。 - -### 二:RAP MOCK,“设计阶段,所有服务全跑通” ### - -在设计阶段写好接口文档后,RAP会根据接口文档中的请求路径、接口数据自动生成所有的服务接口。在联调前,所有MOCK服务全部可跑通,并根据文档变化实时更新,前端自测将变得更加简单。 - -RAP的MOCK数据是动态生成的,默认数据会有自己的初始行为,您也能通过标签精细的控制数据生成的逻辑。这也为后续我们创建”响应参数“的数据创造基础。目前RAP支持[MockJS](http://mockjs.com)和RAP MOCK两种Mock规则,后续还会进行更多扩充 -。 -RAPv0.8请求流程 - -### 三:集合THX平台发挥更大的优势 ### - -RAP生成的数据通过跨平台Crox模板引擎可打通多平台,意味着RAP MOCK的用武之地不再局限于JSONP、JSON形式的接口,Velocity、Smarty等后端模板语言调用RAP MOCK服务依然可行,实现“一处编写、到处使用。” - -我们后续还将与THX其它产品做深度结合,发挥更多的作用。 - -## RAP发展历程 ## - -RAP第一版在2010年中完成开发,历经了3年多的实际应用,无论是文档编辑、前端MOCK服务、后端自测工具还是自动化测试等功能都较为成熟。我们在用户体验、操作细节上也做了很多的努力。 - -在文档结构化后再利用上,接口文档是第一个尝试,我们也在努力挖掘更多的可再利用文档,用以提升其它的重复劳动,我们也在努力让现有功能更加完善。无论你是前端、后端还是测试,有了RAP,文档共享和开发将更为方便。 - -## RAP v1.0 ## - -在即将到来的RAPv1.0版本中,我们会增加分布式的NodeJS客户端,支持Web服务器与RAP的深度结合,利用反向代理解决Mock服务跨域问题,支持离线存取,分散服务器Mock压力,并在客户端实现更多强大的功能。 - -RAPv1.0请求流程 - -RAPv1.0规则编辑和同步流程 - -## 关于RAP ## - -RAP由阿里妈妈用户体验部开发,属于[THX](http://thx.alibaba-inc.com)平台的产品之一。欢迎大家访问[RAP主站](http://rap.alibaba-inc.com),有任何疑问欢迎邮件至:[huoyong.msb@taobao.com](mailto:huoyong.msb@taobao.com)。RAP诚挚的期待您的光临! diff --git a/README.md b/README.md index 3d7ab027b..ee6094f5d 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,29 @@ -Rigel Automation Platform -=== - @version v0.8.1 - @author Bosn(霍雍), wangjeaf(思竹) - @weibo http://weibo.com/bosn, http://github.com/wangjeaf - @mail bosn@outlook.com, wangjeaf@gmail.com +# RAP +![](https://sourcegraph.com/api/repos/github.com/thx/RAP/.counters/views-24h.png) +* [Official Site 官网](http://thx.github.io/RAP) +* [Wiki/Documents/Manual Wiki/文档/手册](http://github.com/thx/RAP/wiki) +* [Video Introduction 视频介绍](http://vodcdn.video.taobao.com/player/ugc/tb_ugc_pieces_core_player_loader.swf?version=1.0.20150330&vid=11622279&uid=11051796&p=1&t=1&rid=&random=6666) +* [Tutorial 教程](http://thx.github.io/RAP/study.html) +* [Issues 反馈问题](http://github.com/thx/RAP/issues) -什么是RAP? --------------------------------------- +RAP can help web engineers create interface doc efficiently, and generate mock data, validate real request by analyzing interface data. With structured API data, RAP can do more while we can do less. -在前后端分离的开发模式下,我们通常需要定义一份`接口文档`来规范接口的具体信息。如一个请求的地址、有几个参数、参数名称及类型含义等等。`RAP` 首先方便团队录入、查看和管理这些接口文档,并通过分析结构化的文档数据,重复利用并生成自测数据、提供自测控制台等等... 大幅度提升开发效率。 +RAP可帮助WEB工程师高效建立接口文档,并生成Mock数据、校验真实接口。通过结构化的API数据,RAP可以做的更多,我们可以做的更少。 + + 一直被抄袭,从未被超越... 2010年到现在良心制作,绝对不是KPI的悲剧产物... + +* 新浪微博:[@Bosn](http://weibo.com/bosn) +* 技术支持:582755829 (旺旺群) + +## About 关于 -- [文档中心](http://thx.alibaba-inc.com/RAP/) + @version v0.11.2 (Apr. 28 2015 updated) + @author @bosn @wangjeaf + @director @limu @xinglie + @dependency MockJS(@nuysoft) + @contact bosn@outlook.com, wangjeaf@gmail.com + +## Contributors List 贡献者 + +`@nunnly`, `@xinglie` diff --git a/WebContent/WEB-INF/lib/codehaus.jackson.core-1.5.4.jar b/WebContent/WEB-INF/lib/codehaus.jackson.core-1.5.4.jar new file mode 100644 index 000000000..61c72dce6 Binary files /dev/null and b/WebContent/WEB-INF/lib/codehaus.jackson.core-1.5.4.jar differ diff --git a/WebContent/WEB-INF/lib/codehaus.jackson.mapper-1.5.4.jar b/WebContent/WEB-INF/lib/codehaus.jackson.mapper-1.5.4.jar new file mode 100644 index 000000000..3bc7833b1 Binary files /dev/null and b/WebContent/WEB-INF/lib/codehaus.jackson.mapper-1.5.4.jar differ diff --git a/WebContent/WEB-INF/lib/commons-codec-1.6.jar b/WebContent/WEB-INF/lib/commons-codec-1.6.jar new file mode 100644 index 000000000..ee1bc49ac Binary files /dev/null and b/WebContent/WEB-INF/lib/commons-codec-1.6.jar differ diff --git a/WebContent/WEB-INF/lib/commons-logging-1.1.3.jar b/WebContent/WEB-INF/lib/commons-logging-1.1.3.jar new file mode 100644 index 000000000..ab5125407 Binary files /dev/null and b/WebContent/WEB-INF/lib/commons-logging-1.1.3.jar differ diff --git a/WebContent/WEB-INF/lib/fluent-hc-4.3.3.jar b/WebContent/WEB-INF/lib/fluent-hc-4.3.3.jar new file mode 100644 index 000000000..609769160 Binary files /dev/null and b/WebContent/WEB-INF/lib/fluent-hc-4.3.3.jar differ diff --git a/WebContent/WEB-INF/lib/httpclient-4.3.3.jar b/WebContent/WEB-INF/lib/httpclient-4.3.3.jar new file mode 100644 index 000000000..6c46bffe4 Binary files /dev/null and b/WebContent/WEB-INF/lib/httpclient-4.3.3.jar differ diff --git a/WebContent/WEB-INF/lib/httpclient-cache-4.3.3.jar b/WebContent/WEB-INF/lib/httpclient-cache-4.3.3.jar new file mode 100644 index 000000000..082430d21 Binary files /dev/null and b/WebContent/WEB-INF/lib/httpclient-cache-4.3.3.jar differ diff --git a/WebContent/WEB-INF/lib/httpcore-4.3.2.jar b/WebContent/WEB-INF/lib/httpcore-4.3.2.jar new file mode 100644 index 000000000..813ec2348 Binary files /dev/null and b/WebContent/WEB-INF/lib/httpcore-4.3.2.jar differ diff --git a/WebContent/WEB-INF/lib/httpmime-4.3.3.jar b/WebContent/WEB-INF/lib/httpmime-4.3.3.jar new file mode 100644 index 000000000..f2b1cf7c8 Binary files /dev/null and b/WebContent/WEB-INF/lib/httpmime-4.3.3.jar differ diff --git a/WebContent/WEB-INF/lib/jakarta.commons.lang-2.4.jar b/WebContent/WEB-INF/lib/jakarta.commons.lang-2.4.jar new file mode 100644 index 000000000..532939eca Binary files /dev/null and b/WebContent/WEB-INF/lib/jakarta.commons.lang-2.4.jar differ diff --git a/WebContent/WEB-INF/lib/log4j-1.2.15.jar b/WebContent/WEB-INF/lib/jakarta.log4j-1.2.15.jar similarity index 100% rename from WebContent/WEB-INF/lib/log4j-1.2.15.jar rename to WebContent/WEB-INF/lib/jakarta.log4j-1.2.15.jar diff --git a/WebContent/WEB-INF/lib/javax.mail.jar b/WebContent/WEB-INF/lib/javax.mail.jar new file mode 100644 index 000000000..ca7eca7d9 Binary files /dev/null and b/WebContent/WEB-INF/lib/javax.mail.jar differ diff --git a/WebContent/WEB-INF/lib/log4j-api-2.0.2.jar b/WebContent/WEB-INF/lib/log4j-api-2.0.2.jar new file mode 100644 index 000000000..35a9a5b60 Binary files /dev/null and b/WebContent/WEB-INF/lib/log4j-api-2.0.2.jar differ diff --git a/WebContent/WEB-INF/lib/log4j-core-2.0.2.jar b/WebContent/WEB-INF/lib/log4j-core-2.0.2.jar new file mode 100644 index 000000000..6588c3155 Binary files /dev/null and b/WebContent/WEB-INF/lib/log4j-core-2.0.2.jar differ diff --git a/WebContent/WEB-INF/lib/mail.jar b/WebContent/WEB-INF/lib/mail.jar deleted file mode 100644 index aa357d4b9..000000000 Binary files a/WebContent/WEB-INF/lib/mail.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/org.slf4j.slf4j-api-1.5.6.jar b/WebContent/WEB-INF/lib/org.slf4j.slf4j-api-1.5.6.jar new file mode 100644 index 000000000..9b4221694 Binary files /dev/null and b/WebContent/WEB-INF/lib/org.slf4j.slf4j-api-1.5.6.jar differ diff --git a/WebContent/WEB-INF/lib/org.slf4j.slf4j-log4j12-1.5.6.jar b/WebContent/WEB-INF/lib/org.slf4j.slf4j-log4j12-1.5.6.jar new file mode 100644 index 000000000..0c40e9c8b Binary files /dev/null and b/WebContent/WEB-INF/lib/org.slf4j.slf4j-log4j12-1.5.6.jar differ diff --git a/WebContent/WEB-INF/lib/pinyin4j-2.5.0.jar b/WebContent/WEB-INF/lib/pinyin4j-2.5.0.jar new file mode 100644 index 000000000..e8ede137a Binary files /dev/null and b/WebContent/WEB-INF/lib/pinyin4j-2.5.0.jar differ diff --git a/WebContent/WEB-INF/lib/prettytime-3.2.3.Final.jar b/WebContent/WEB-INF/lib/prettytime-3.2.3.Final.jar new file mode 100644 index 000000000..55a84c387 Binary files /dev/null and b/WebContent/WEB-INF/lib/prettytime-3.2.3.Final.jar differ diff --git a/WebContent/WEB-INF/toolbox.xml b/WebContent/WEB-INF/toolbox.xml index 92fe92234..fe6d4c7de 100644 --- a/WebContent/WEB-INF/toolbox.xml +++ b/WebContent/WEB-INF/toolbox.xml @@ -1,17 +1,27 @@ - - - - version - 1.3 - - - utils - application - com.taobao.rigel.rap.common.StringUtils - - - dateUtils - application - com.taobao.rigel.rap.common.DateUtils - - + + + + version + 1.3 + + + utils + application + com.taobao.rigel.rap.common.StringUtils + + + dateUtils + application + com.taobao.rigel.rap.common.DateUtils + + + consts + application + com.taobao.rigel.rap.common.SystemConstant + + + logger + application + com.taobao.rigel.rap.common.SystemVisitorLog + + diff --git a/WebContent/WEB-INF/urlrewrite.xml b/WebContent/WEB-INF/urlrewrite.xml index 52fa92059..e11114ca3 100644 --- a/WebContent/WEB-INF/urlrewrite.xml +++ b/WebContent/WEB-INF/urlrewrite.xml @@ -36,4 +36,11 @@ ^/rap.plugin.js(.*)$ /mock/createPluginScript.action$1 + + + node doc service + + ^/doc/(\d*)$ + http://localhost:7429/doc/$1.html + \ No newline at end of file diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 2abd8ff3f..622aee100 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -25,7 +25,7 @@ SSO_SERVER_URL - https://login.alibaba-inc.com + [TODO]:這裡寫LOGIN_URL CLIENT_KEY @@ -33,7 +33,7 @@ EXCLUSIONS - */stat/*,*/favicon.ico,/t/*,/crossdomain.xml,/*.htm,/*.html,*.md,*/mock/*,*/mockjs/*,*/mockjsdata/*,/rap.plugin.js + * @@ -80,10 +80,6 @@ DelegatingFilterProxy /* - - authCheckFilter - /* - UrlRewriteFilter /* diff --git a/WebContent/account/login.vm b/WebContent/account/login.vm index b3f306f02..c0405d881 100644 --- a/WebContent/account/login.vm +++ b/WebContent/account/login.vm @@ -1,42 +1,45 @@ - -#parse('/tcom/template.rap.vm') + - - - Login - #includeRapStatic + + + Login + #parse('/tcom/template.rap.vm') + #includeNewRapStatic + #if($returnUrlFirstSet) + #set($returnUrlEncoded = $!utils.escapeInU($returnUrl)) + #else + #set($returnUrlEncoded = $returnUrl) + #end - - - #bodyStart -
- - - - - - - - - - - - - - - - - - #if ($errMsg && $errMsg != "") - - - - - #end -

登录

用户名:
密    码:
$!errMsg
+ + +
+ #bodyNewStart + + +
+ + +
+
+ + +
+ #if ($errMsg && $errMsg != "") +
+
+ $!errMsg +
+
+ #end +    + + 域账号登录 + - #bodyEnd - + #bodyEnd +
+ diff --git a/WebContent/account/myAccount.vm b/WebContent/account/myAccount.vm index f1b21819e..6d2f77792 100644 --- a/WebContent/account/myAccount.vm +++ b/WebContent/account/myAccount.vm @@ -1,15 +1,16 @@ - + #parse('/tcom/template.rap.vm') + Manage Account #includeNewRapStatic @@ -18,7 +19,7 @@ #if($isEditMode)
#end - +
@@ -71,19 +72,19 @@ - + + - + --> ]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"
用户名: $!curUser.account上次登录: $!curUser.lastLoginDateStr
diff --git a/WebContent/account/mySetting.vm b/WebContent/account/mySetting.vm new file mode 100644 index 000000000..9b931ee9f --- /dev/null +++ b/WebContent/account/mySetting.vm @@ -0,0 +1,150 @@ + +#parse('/tcom/template.rap.vm') + + + + +Manage Account #includeNewRapStatic + + + + #bodyNewStart + +
+
不要鸡冻,这个功能还木有做完,霍雍和思竹吃饭饭去了
+ + + +
+
+ +
+ +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+
+ + +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+
+ + +
+
+
+
+
更多功能,敬请期待~
+
+
+ #bodyEnd + + diff --git a/WebContent/account/register.vm b/WebContent/account/register.vm index 3677b4351..d4ae4f19c 100644 --- a/WebContent/account/register.vm +++ b/WebContent/account/register.vm @@ -1,45 +1,46 @@ - + #parse('/tcom/template.rap.vm') - - - Register New Account - #includeRapStatic - - - #bodyStart -
-
-
-
-
用户名:
-
-
-
-
密码:
-
-
-
-
确认密码:
-
-
-
-
Email:
-
-
-
-
名字:
-
-
-
-
-
-
-
$!errMsg
-
-
-
-
- #bodyEnd - + + + 注册新的RAP账户 + #includeNewRapStatic + + + #bodyNewStart +
+
+
+
+
用户名:
+
+
+
+
密码:
+
+
+
+
确认密码:
+
+
+
+
Email:
+
+
+
+
名字:
+
+
+
+
+
+
+

+
#if($errMsg)$errMsg#else 用户名已存在,或其它错误。 #end
+
+
+
+
+ #bodyEnd + diff --git a/WebContent/bcom/contentWithoutEscape.cb.vm b/WebContent/bcom/contentWithoutEscape.cb.vm index 39013f8ac..2044ad03d 100644 --- a/WebContent/bcom/contentWithoutEscape.cb.vm +++ b/WebContent/bcom/contentWithoutEscape.cb.vm @@ -1 +1 @@ -$!content \ No newline at end of file +$!content \ No newline at end of file diff --git a/WebContent/common/redirect.vm b/WebContent/common/redirect.vm index 64e7e0e81..d85883540 100644 --- a/WebContent/common/redirect.vm +++ b/WebContent/common/redirect.vm @@ -1,4 +1,4 @@ - + diff --git a/WebContent/demo/a.js b/WebContent/demo/a.js new file mode 100644 index 000000000..0e11d983e --- /dev/null +++ b/WebContent/demo/a.js @@ -0,0 +1,13 @@ +define(function(require, exports, module) { + var $ = require('jquery'); + exports.go = function() { + $.ajax({ + url : 'data.json', + dataType : 'json', + type : 'get', + success : function(data) { + $('body').html(JSON.stringify(data, null, 4)); + } + }); + } +}) \ No newline at end of file diff --git a/WebContent/demo/mock.plugin/casebox/case1_seajs_jquery_preload.html b/WebContent/demo/mock.plugin/casebox/case1_seajs_jquery_preload.html new file mode 100644 index 000000000..c6f548e8a --- /dev/null +++ b/WebContent/demo/mock.plugin/casebox/case1_seajs_jquery_preload.html @@ -0,0 +1,60 @@ + + + + + + + + + +
+
+

+ RAP plugin case1: seajs jquery preload issue. +

+

LOG:

+

+
+ + + + + \ No newline at end of file diff --git a/WebContent/demo/mock.plugin/index.htm b/WebContent/demo/mock.plugin/index.htm index 8deba87b9..b2c54b501 100644 --- a/WebContent/demo/mock.plugin/index.htm +++ b/WebContent/demo/mock.plugin/index.htm @@ -6,17 +6,17 @@ - +

     
 
 
diff --git a/WebContent/demo/seajs-plugin.html b/WebContent/demo/seajs-plugin.html
new file mode 100644
index 000000000..88296830a
--- /dev/null
+++ b/WebContent/demo/seajs-plugin.html
@@ -0,0 +1,24 @@
+
+
+
+
+RAP Example
+
+
+
+
+
+
+
+    

+    
+
+
diff --git a/WebContent/error.vm b/WebContent/error.vm
index 0781c2d3f..6f8134e80 100644
--- a/WebContent/error.vm
+++ b/WebContent/error.vm
@@ -4,17 +4,17 @@
 	
 		
 		我勒个去!出错了 T.T       
-		#includeRapStatic
+        #includeNewRapStatic
 	
 	
-	#bodyStart
+    #bodyNewStart
 	
-

ERROR

+

RAP出错啦!

-
+ diff --git a/WebContent/index.htm b/WebContent/index.htm index 8075d7ed8..f08f2e4c5 100644 --- a/WebContent/index.htm +++ b/WebContent/index.htm @@ -1,4 +1,4 @@ - + diff --git a/WebContent/mock/createPluginScript.vm b/WebContent/mock/createPluginScript.vm index c7e749752..04f399245 100644 --- a/WebContent/mock/createPluginScript.vm +++ b/WebContent/mock/createPluginScript.vm @@ -1,3 +1,4 @@ +#include('/stat/js/util/console-compability.js') #include('/stat/js/util/structureValidator.js') #include('/stat/js/util/mock-min.js') #parse('/stat/js/util/mock.plugin.js') \ No newline at end of file diff --git a/WebContent/mock/dist/mock-min.map b/WebContent/mock/dist/mock-min.map new file mode 100644 index 000000000..95a2f6069 --- /dev/null +++ b/WebContent/mock/dist/mock-min.map @@ -0,0 +1 @@ +{"version":3,"file":"dist/mock-min.js","sources":["dist/mock.js"],"names":["undefined","find","options","match","expected","actual","Util","type","test","sUrlType","Mock","_mocked","item","rurl","url","rtype","toLowerCase","convert","isFunction","template","mock","version","extend","name","src","copy","clone","target","arguments","i","length","this","isArray","isObject","each","obj","iterator","context","key","call","String","Object","prototype","toString","split","value","isObjectOrArray","isNumeric","isNaN","parseFloat","isFinite","keys","hasOwnProperty","push","values","heredoc","fn","replace","noop","Random","boolean","min","max","cur","parseInt","Math","random","bool","natural","round","integer","int","float","dmin","dmax","ret","dcount","character","pool","pools","lower","upper","number","symbol","alpha","charAt","char","string","text","str","range","start","stop","step","len","ceil","idx","Array","patternLetters","yyyy","yy","date","getFullYear","slice","y","MM","m","getMonth","M","dd","d","getDate","HH","h","getHours","H","hh","mm","getMinutes","ss","s","getSeconds","SS","ms","getMilliseconds","S","A","a","T","rformat","RegExp","re","join","format","$0","flag","callee","randomDate","Date","getTime","time","datetime","now","unit","setMonth","setDate","setHours","setMinutes","setSeconds","setMilliseconds","getDay","ad_size","screen_size","video_size","image","size","background","foreground","pick","indexOf","img","apply","brandColors","4ormat","500px","About.me (blue)","About.me (yellow)","Addvocate","Adobe","Aim","Amazon","Android","Angie's List","AOL","Atlassian","Behance","Big Cartel","bitly","Blogger","Boeing","Booking.com","Carbonmade","Cheddar","Code School","Delicious","Dell","Designmoo","Deviantart","Designer News","Devour","DEWALT","Disqus (blue)","Disqus (orange)","Dribbble","Dropbox","Drupal","Dunked","eBay","Ember","Engadget","Envato","Etsy","Evernote","Fab.com","Facebook","Firefox","Flickr (blue)","Flickr (pink)","Forrst","Foursquare","Garmin","GetGlue","Gimmebar","GitHub","Google Blue","Google Green","Google Red","Google Yellow","Google+","Grooveshark","Groupon","Hacker News","HelloWallet","Heroku (light)","Heroku (dark)","HootSuite","Houzz","HTML5","IKEA","IMDb","Instagram","Intel","Intuit","Kickstarter","kippt","Kodery","LastFM","LinkedIn","Livestream","Lumo","Mixpanel","Meetup","Nokia","NVIDIA","Opera","Path","PayPal (dark)","PayPal (light)","Pinboard","Pinterest","PlayStation","Pocket","Prezi","Pusha","Quora","QUOTE.fm","Rdio","Readability","Red Hat","Resource","Rockpack","Roon","RSS","Salesforce","Samsung","Shopify","Skype","Snagajob","Softonic","SoundCloud","Space Box","Spotify","Sprint","Squarespace","StackOverflow","Staples","Status Chart","Stripe","StudyBlue","StumbleUpon","T-Mobile","Technorati","The Next Web","Treehouse","Trulia","Tumblr","Twitch.tv","Twitter","TYPO3","Ubuntu","Ustream","Verizon","Vimeo","Vine","Virb","Virgin Media","Wooga","WordPress (blue)","WordPress (orange)","WordPress (grey)","Wunderlist","XBOX","XING","Yahoo!","Yandex","Yelp","YouTube","Zalongo","Zendesk","Zerply","Zootool","brands","b","dataImage","canvas","document","createElement","ctx","getContext","width","height","text_height","font","textAlign","textBaseline","fillStyle","fillRect","fillText","toDataURL","color","colour","floor","capitalize","word","toUpperCase","substr","arr","shuffle","old","result","index","splice","paragraph","sentence","title","first","names","concat","last","middle","domain","tld","email","ip","tlds","areas","area","regions","region","address","city","phone","areacode","street","street_suffixes","street_suffix","states","state","zip","todo","d4","d6","d8","d12","d20","d100","guid","id","sum","rank","autoIncrementInteger","increment","inc","rkey","rrange","rplaceholder","Handle","gen","rule","parameters","count","decimal","point","path","templatePath","currentContext","templateCurrentContext","root","templateRoot","parsedName","array","j","pop","object","fnKeys","parsedKey","parts","placeholders","ph","phed","placeholder","function","_all","templateContext","exec","lkey","okey","params","eval","error","handle","mockjax","jQuery","mockxhr","readyState","status","statusText","open","send","onload","setRequestHeader","getAllResponseHeaders","getResponseHeader","statusCode","abort","prefilter","originalOptions","dataFilter","converters","xhr","dataType","ajaxPrefilter","Zepto","__original_ajax","ajax","responseText","responseXML","timeoutTimer","data","success","complete","KISSY","add","_original_ajax","io","module","exports","define","amd","cmd","requires","Mock4Tpl","tpl","input","helpers","partials","parse","Handlebars","debug","node","isString","ast","parseOptions","__path","console","log","group","JSON","stringify","preLength","groupEnd","ma","option","rComment","comments","lastIndex","Function","val","def","Error","mocked","program","statements","mustache","contextLength","unshift","isHelper","hash","block","inverse","Helpers","custom","shift","pair","pairs","ID","prev","valType","preOptions","depth","partial","partialName","content","PARTIAL_NAME","DATA","STRING","INTEGER","BOOLEAN","comment","unless","XTemplate","Mock4XTpl","use","xtpl","xparse","compiler","RunTime","commands","subTpls","other","hold","parseVal","expr","queryArray","prop","query","queryObject","set","if","with","_","__","___","include","tplExpression","expression","unaryExpression","multiplicativeExpression","additiveExpression","op1","op2","pow","relationalExpression","equalityExpression","conditionalAndExpression","conditionalOrExpression","fix"],"mappings":"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"} \ No newline at end of file diff --git a/WebContent/org/group/index.css b/WebContent/org/group/index.css index 72f366b69..67842e42d 100644 --- a/WebContent/org/group/index.css +++ b/WebContent/org/group/index.css @@ -85,28 +85,6 @@ overflow: hidden; } -@-webkit-keyframes spaceboots { - 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); } - 10% { -webkit-transform: translate(-1px, -2px) rotate(-1deg); } - 20% { -webkit-transform: translate(-3px, 0px) rotate(1deg); } - 30% { -webkit-transform: translate(0px, 2px) rotate(0deg); } - 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); } - 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); } - 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); } - 70% { -webkit-transform: translate(2px, 1px) rotate(-1deg); } - 80% { -webkit-transform: translate(-1px, -1px) rotate(1deg); } - 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); } - 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); } -} -.shake { - -webkit-animation-name: spaceboots; - -webkit-animation-duration: 0.8s; - -webkit-transform-origin:50% 50%; - -webkit-animation-iteration-count: 2; - -webkit-animation-timing-function: linear; - display:inline-block -} - .groups-con .groups .group .box .status { position: absolute; bottom: 0; @@ -237,32 +215,11 @@ .project-target .productline {width: 30%; float: left; margin-left: 10px;} .project-target .group {width: 30%; float: left; margin-left: 10px;} -.project-autocomplete-con { - width: 400px; font-size: 14px; position: absolute; left: 0; top: 35px; background-color: #FFF; border: 1px solid #CCC; z-index: 1000 -} -.project-autocomplete-con ul { - margin-bottom: 0; -} -.project-autocomplete-con li { - cursor: pointer; padding: 6px 11px; line-height: 20px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; -} -.project-autocomplete-con li:nth-child(odd) { - background-color: #F9F9F9; -} -.project-autocomplete-con li:hover, .project-autocomplete-con li.active { - background-color: #F2F2F2; -} -.search-project-con { - width: 400px; display: inline-block; margin-left: 20px; position: relative; -} - -.search-project-con .glyphicon-search { - position: absolute; - font-size: 14px; - right: 8px; - top: 10px; - color: #CCC; -} -.project-search-inputer { - padding-right: 25px; +.groups .status .creator { + position: absolute; + font-size: 12px; + color: #FFF; + text-shadow: 0 0 2px rgba(0,0,0,.4); + right: 2px; + bottom: 0; } \ No newline at end of file diff --git a/WebContent/org/group/index.js b/WebContent/org/group/index.js index f9abdc7ac..5d4bbc945 100644 --- a/WebContent/org/group/index.js +++ b/WebContent/org/group/index.js @@ -114,74 +114,79 @@ $(function() { }) } } - getUsers(function(users) { - $.confirm({ - content: $.render($('#create-proj-tmpl').text(), { - name: name, - desc: desc, - users: pickeds - }), - title: '修改项目', - confirmText: '确认修改', - showCallback: function() { - var that = this; - $(this).find('input[type=text]').focus(); - $(this).find('.picking-user').delegate('.unpick-btn', 'click', function() { - $(this).parent('.picked-user').remove(); - }); - $(this).find('.accounts-inputer').keyup(function() { + $.confirm({ + content: $.render($('#create-proj-tmpl').text(), { + name: name ? name.replace(/"/g, "") : "", + desc: desc, + users: pickeds + }), + title: '修改项目', + confirmText: '确认修改', + showCallback: function() { + var that = this; + $(this).find('input[type=text]').focus(); + $(this).find('.picking-user').delegate('.unpick-btn', 'click', function() { + $(this).parent('.picked-user').remove(); + }); + + getUsers(function(users) { + $('.user-loading').hide(); + $(that).find('.accounts-inputer').keyup(function() { $.autocomplete(that, users); }).focus(function() { $.autocomplete(that, users); }); - }, - confirmClicked: function() { - var inputer = $(this).find('input[type=text]'); - if (inputer.val().trim() == '') { - inputer.addClass('shake'); - inputer.focus(); - setTimeout(function() { - inputer && inputer.removeClass('shake'); - }, 1000); + }); + }, + confirmClicked: function() { + var inputer = $(this).find('input[type=text]'); + if (inputer.val().trim() == '') { + inputer.addClass('shake'); + inputer.focus(); + setTimeout(function() { + inputer && inputer.removeClass('shake'); + }, 1000); + return; + } + var tmpl = $('#create-proj-success-tmpl').text(); + var modal = $(this); + var accounts = $(this).find('.picked-user'); + var values = []; + for(var i = 0, l = accounts.length; i < l; i++) { + var current = $(accounts[i]); + values.push(current.data('account') + '(' + current.data('name') + ')') + } + $.post($.route('org.project.update'), { + id: id, + name: inputer.val(), + desc: $(this).find('textarea.desc').val(), + accounts: values.join(', ') + }, function(data) { + if (data.code != '200') { + modal.modal('hide'); + alert(data.msg); return; } - var tmpl = $('#create-proj-success-tmpl').text(); - var modal = $(this); - var accounts = $(this).find('.picked-user'); - var values = []; - for(var i = 0, l = accounts.length; i < l; i++) { - var current = $(accounts[i]); - values.push(current.data('account') + '(' + current.data('name') + ')') - } - $.post($.route('org.project.update'), { - id: id, - name: inputer.val(), - desc: $(this).find('textarea.desc').val(), - accounts: values.join(', ') - }, function(data) { - if (data.code != '200') { - modal.modal('hide'); - alert(data.msg); - return; - } - var data = data.result; - data.status = data.status || '刚刚更新'; - var html = $.render(tmpl, data); - box.replaceWith(html); - modal.modal('hide'); - }, "JSON") - } - }); + var data = data.result; + data.status = data.status || '刚刚更新'; + var html = $.render(tmpl, data); + box.replaceWith(html); + modal.modal('hide'); + }, "JSON") + } }); }) .delegate('.box .glyphicon-export', 'click', function() { var id = $(this).data('id'); var url = ''; + var host = location && location.host ? location.host : '/'; $.message({ - content: '', + content: '', title: '复制RAP插件地址', showCallback: function() { - $('#rap-plugin-inputer').focus(); + var ele = $('#rap-plugin-inputer')[0]; + ele.focus(); + ele.selectionEnd = ele.value.length; } }); }) @@ -212,55 +217,56 @@ $(function() { .delegate('.box-to-add', 'click', function() { var that = this; var groupId = $(this).data('groupid'); - getUsers(function(users) { - $.confirm({ - content: $.render($('#create-proj-tmpl').text(), {}), - title: '创建项目', - confirmText: '确认创建', - showCallback: function() { - var that = this; - $(this).find('input[type=text]').focus(); - $(this).find('.picking-user').delegate('.unpick-btn', 'click', function() { - $(this).parent('.picked-user').remove(); - }); - $(this).find('.accounts-inputer').keyup(function() { + $.confirm({ + content: $.render($('#create-proj-tmpl').text(), {}), + title: '创建项目', + confirmText: '确认创建', + showCallback: function() { + var that = this; + $(this).find('input[type=text]').focus(); + $(this).find('.picking-user').delegate('.unpick-btn', 'click', function() { + $(this).parent('.picked-user').remove(); + }); + getUsers(function(users) { + $('.user-loading').hide(); + $(that).find('.accounts-inputer').keyup(function() { $.autocomplete(that, users); }).focus(function() { $.autocomplete(that, users); }); - }, - confirmClicked: function() { - var inputer = $(this).find('input[type=text]'); - if (inputer.val().trim() == '') { - inputer.addClass('shake'); - inputer.focus(); - setTimeout(function() { - inputer && inputer.removeClass('shake'); - }, 1000); - return; - } - var tmpl = $('#create-proj-success-tmpl').text(); - var modal = $(this); - var accounts = $(this).find('.picked-user'); - var values = []; - for(var i = 0, l = accounts.length; i < l; i++) { - var current = $(accounts[i]); - values.push(current.data('account') + '(' + current.data('name') + ')') - } - $.post($.route('org.project.create'), { - groupId: groupId, - name: inputer.val(), - desc: $(this).find('textarea.desc').val(), - accounts: values.join(', ') - }, function(data) { - var data = data.result; - data.status = data.status || '刚刚创建'; - var html = $.render(tmpl, data); - $(that).before(html); - modal.modal('hide'); - }, "JSON") + }); + }, + confirmClicked: function() { + var inputer = $(this).find('input[type=text]'); + if (inputer.val().trim() == '') { + inputer.addClass('shake'); + inputer.focus(); + setTimeout(function() { + inputer && inputer.removeClass('shake'); + }, 1000); + return; } - }); + var tmpl = $('#create-proj-success-tmpl').text(); + var modal = $(this); + var accounts = $(this).find('.picked-user'); + var values = []; + for(var i = 0, l = accounts.length; i < l; i++) { + var current = $(accounts[i]); + values.push(current.data('account') + '(' + current.data('name') + ')') + } + $.post($.route('org.project.create'), { + groupId: groupId, + name: inputer.val(), + desc: $(this).find('textarea.desc').val(), + accounts: values.join(', ') + }, function(data) { + var data = data.result; + data.status = data.status || '刚刚创建'; + var html = $.render(tmpl, data); + $(that).before(html); + modal.modal('hide'); + }, "JSON") + } }); }) .delegate('.save-update-group', 'click', function() { diff --git a/WebContent/org/group/index.vm b/WebContent/org/group/index.vm index 296c57f67..21a5ce6d9 100644 --- a/WebContent/org/group/index.vm +++ b/WebContent/org/group/index.vm @@ -1,9 +1,10 @@ - + #parse('/tcom/template.rap.vm') 欢迎使用RAP + #includeNewRapStatic @@ -40,7 +41,7 @@
{{name}}
{{desc}}
-
{{status}}
+
{{status}}@{{creator.name}}
{{#important}}
{{/important}} @@ -66,9 +67,10 @@
{{name}}
{{desc}}
-
{{status}}
+
{{status}}@{{creator.name}}
+
@@ -91,13 +93,13 @@
- +
- +
@@ -107,6 +109,7 @@ {{account}} ({{name}})× {{/users}} + 项目成员列表加载中,请稍候~
diff --git a/WebContent/org/home/index.js b/WebContent/org/home/index.js index f29c93949..e6a2130ed 100644 --- a/WebContent/org/home/index.js +++ b/WebContent/org/home/index.js @@ -4,12 +4,17 @@ $(function() { // console.log(data.isOk); //}, 'JSON'); + if (!-[1,]) { // IE 6-8 + $('#browserCheckAlert').show(); + } + var NAME_MAP = { 'user': '我的项目', 'star': '重要项目', - 'heart': '我关注的项目' + 'heart': '我关注的项目', + 'tag': '我加入的项目' }; - + var PL_ID = null; var CORP_ID = null; function getUsers(callback) { @@ -23,69 +28,69 @@ $(function() { callback(users); }, "JSON"); } - + function handleAddClick() { - var that = this; - var btn = $(this); - if (btn.data('shown')) { - return; - } - btn.data('shown', 1); + var that = this; + var btn = $(this); + if (btn.data('shown')) { + return; + } + btn.data('shown', 1); var groupId = $(this).data('groupid'); - + $.confirm({ content: $.render($('#create-proj-tmpl').text(), {}), title: '创建项目', confirmText: '确认创建', cancelCallback: function() { - btn.data('shown', 0); + btn.data('shown', 0); }, showCallback: function() { - btn.data('shown', 0); + btn.data('shown', 0); var that = this; $(this).find('input[type=text]').focus(); $(this).find('.picking-user').delegate('.unpick-btn', 'click', function() { $(this).parent('.picked-user').remove(); }); - + $('.tip').tooltip(); $('.project-target .team').change(function() { var corpId = $(this).val(); if (corpId === '') { - CORP_ID = ''; - $('.create-new-entity-container').html(''); + CORP_ID = ''; + $('.create-new-entity-container').html(''); return; } var text = $(this).find('[value=' + corpId + ']').text(); - + fillSelectAsync('org.productline.all', { corpId: corpId }, $('#option-list-tmpl').text(), '.project-target .productline', function() { - showCreateProductlineBtn(corpId, text); + showCreateProductlineBtn(corpId, text); }); }); - + $('.project-target .productline').change(function() { var plId = $(this).val(); if (!plId) { - PL_ID = ''; - $('.create-new-entity-container').html(''); + PL_ID = ''; + $('.create-new-entity-container').html(''); return; } var text = $(this).find('[value=' + plId + ']').text(); - fillSelectAsync('org.group.all', { + fillSelectAsync('org.home.grouplist', { productLineId: plId }, $('#option-list-tmpl').text(), '.project-target .group', function() { - showCreateGroupBtn(plId, text); + showCreateGroupBtn(plId, text); }); }); - + getUsers(function(users) { - $('.user-loading').hide(); - $(that).find('.accounts-inputer').keyup(function() { - $.autocomplete(that, users); - }).focus(function() { - $.autocomplete(that, users); - }); + $('.user-loading').hide(); + $(that).find('.accounts-inputer').keyup(function() { + $.autocomplete(that, users); + }).focus(function() { + $.autocomplete(that, users); + }); }); }, confirmClicked: function() { @@ -133,16 +138,16 @@ $(function() { } }); } - + function handleViewProjectClick() { - var box = $(this); + var box = $(this); box = box.parents('.box'); var projId = box.data('projid'); - window.open($.route('workspace.mine') + '?projectId=' + projId); + window.location = ($.route('workspace.mine') + '?projectId=' + projId); } - + function handleEditProjectClick() { - var id = $(this).data('id'); + var id = $(this).data('id'); var box = $(this).parents('.box'); var name = box.find('.info .title').html(); var desc = box.find('.info .intro').html(); @@ -161,7 +166,7 @@ $(function() { } $.confirm({ content: $.render($('#update-proj-tmpl').text(), { - name: name, + name: name ? name.replace(/"/g, "") : "", desc: desc, users: pickeds }), @@ -173,14 +178,14 @@ $(function() { $(this).find('.picking-user').delegate('.unpick-btn', 'click', function() { $(this).parent('.picked-user').remove(); }); - + $('.tip').tooltip(); getUsers(function(users) { - $('.user-loading').hide(); - $(that).find('.accounts-inputer').keyup(function() { - $.autocomplete(that, users); - }).focus(function() { - $.autocomplete(that, users); - }); + $('.user-loading').hide(); + $(that).find('.accounts-inputer').keyup(function() { + $.autocomplete(that, users); + }).focus(function() { + $.autocomplete(that, users); + }); }); }, confirmClicked: function() { @@ -221,125 +226,128 @@ $(function() { } }); } - + function handleRapPluginClick() { - var id = $(this).data('id'); - var url = ''; - $.message({ - content: '', + var id = $(this).data('id'); + var url = ''; + var host = location && location.host ? location.host : '/'; + $.message({ + content: '', title: '复制RAP插件地址', showCallback: function() { - $('#rap-plugin-inputer').focus(); + var ele = $('#rap-plugin-inputer')[0]; + ele.focus(); + ele.selectionEnd = ele.value.length; } - }); + }); } - + function handleCreateProductline() { - $.confirm({ - content: $.render($('#create-productline').text(), {}), - title: '添加产品线', - confirmText: '确定', - showCallback: function() { - $(this).find('input[type=text]').focus(); - }, - confirmClicked: function() { - var inputer = $(this).find('input[type=text]'); - if (inputer.val().trim() == '') { - inputer.addClass('shake'); - inputer.focus(); - setTimeout(function() { - inputer && inputer.removeClass('shake'); - }, 1000); - return; - } - var modal = $(this); - var value = inputer.val().trim(); - $.post($.route('org.productline.create'), { - corpId: CORP_ID, - name: value - }, function(data) { - var productlines = data.items; - if (!productlines) { - alert('创建失败,请稍后再试'); - return; - } - var pl = productlines[0]; - showCreateGroupBtn(pl.id, pl.name) - resetGroupSelect(); - var select = appendOptions('.project-target .productline', pl.id, pl.name); - setTimeout(function() { - select.find('[value=""]').text('--请选择--'); - select.val(pl.id); - }, 100); - modal.modal('hide'); - }, "JSON") - } - }); + $.confirm({ + content: $.render($('#create-productline').text(), {}), + title: '添加产品线', + confirmText: '确定', + showCallback: function() { + $(this).find('input[type=text]').focus(); + }, + confirmClicked: function() { + var inputer = $(this).find('input[type=text]'); + if (inputer.val().trim() === '') { + inputer.addClass('shake'); + inputer.focus(); + setTimeout(function() { + inputer && inputer.removeClass('shake'); + }, 1000); + return; + } + var modal = $(this); + var value = inputer.val().trim(); + $.post($.route('org.productline.create'), { + corpId: CORP_ID, + name: value + }, function(data) { + var productlines = data.items; + if (!productlines) { + alert('创建失败,请稍后再试'); + return; + } + var pl = productlines[0]; + showCreateGroupBtn(pl.id, pl.name); + resetGroupSelect(); + var select = appendOptions('.project-target .productline', pl.id, pl.name); + setTimeout(function() { + select.find('[value=""]').text('--请选择--'); + select.val(pl.id); + }, 100); + modal.modal('hide'); + }, "JSON"); + } + }); } - + function appendOptions(selector, value, text) { - return $(selector).append('') + return $(selector).append(''); } - + function showCreateGroupBtn(id, name) { - PL_ID = id; - $('.create-new-entity-container').hide().html( - '
为 “' + name + '” 产品线创建新分组
').slideDown(); + PL_ID = id; + $('.create-new-entity-container').hide().html( + '
为 “' + name + '” 产品线创建新分组
').slideDown(); } - + function showCreateProductlineBtn(id, name) { - CORP_ID = id; - $('.create-new-entity-container').hide().html( - '
为 “' + name + '” 创建新产品线
').slideDown(); + CORP_ID = id; + $('.create-new-entity-container').hide().html( + '
为 “' + name + '” 创建新产品线
').slideDown(); } - + function resetGroupSelect() { - $('.project-target .group').html('') + $('.project-target .group').html(''); } - + function handleCreateGroup() { - $.confirm({ - content: $('#create-group-tmpl').text(), - title: '创建分组', - confirmText: '确认创建', - showCallback: function() { - $(this).find('input[type=text]').focus(); - }, - confirmClicked: function() { - var tmpl = $('#group-tmpl').text(); - var inputer = $(this).find('input[type=text]'); - if (inputer.val().trim() == '') { - inputer.addClass('shake'); - inputer.focus(); - setTimeout(function() { - inputer && inputer.removeClass('shake'); - }, 1000); - return; - } - var modal = $(this); - $.post($.route('org.group.create'), { - productLineId: PL_ID, - name: inputer.val().trim() - }, function(data) { - var groups = data.groups; - if (!groups) { - alert('创建失败,请稍后再试'); - return; - } - var group = groups[0]; - var select = $('.project-target .group').append(''); - setTimeout(function() { - select.find('[value=""]').text('--请选择--'); - select.val(group.id); - }, 100); - modal.modal('hide'); - }, "JSON") - } - }); + $.confirm({ + content: $('#create-group-tmpl').text(), + title: '创建分组', + confirmText: '确认创建', + showCallback: function() { + $(this).find('input[type=text]').focus(); + }, + confirmClicked: function() { + var tmpl = $('#group-tmpl').text(); + var inputer = $(this).find('input[type=text]'); + if (inputer.val().trim() === '') { + inputer.addClass('shake'); + inputer.focus(); + setTimeout(function() { + inputer && inputer.removeClass('shake'); + }, 1000); + return; + } + var modal = $(this); + $.post($.route('org.group.create'), { + productLineId: PL_ID, + name: inputer.val().trim() + }, function(data) { + var groups = data.groups; + if (!groups) { + alert('创建失败,请稍后再试'); + return; + } + var group = groups[0]; + var select = $('.project-target .group').append(''); + setTimeout(function() { + select.find('[value=""]').text('--请选择--'); + select.val(group.id); + }, 100); + modal.modal('hide'); + }, "JSON"); + } + }); } - + function handleDeleteClick() { - var id = $(this).data('id'); + var id = $(this).data('id'); var box = $(this).parents('.box'); $.confirm({ content: '删除以后不可恢复,请谨慎操作', @@ -369,14 +377,14 @@ $(function() { .delegate('.box .glyphicon-pencil', 'click', handleEditProjectClick) .delegate('.box .glyphicon-export', 'click', handleRapPluginClick) .delegate('.create-productline', 'click', handleCreateProductline) - .delegate('.create-group', 'click', handleCreateGroup) + .delegate('.create-group', 'click', handleCreateGroup) .delegate('.box .glyphicon-trash', 'click', handleDeleteClick); } function fillSelectAsync(route, params, tmpl, target, callback) { callback && callback(); $(target).html($.render(tmpl, { - items: [{id: '', name: '加载中...'}] + items: [{id: '', name: '加载中...'}] })); $.get($.route(route), params, function(data) { if (data.groups) { @@ -508,11 +516,25 @@ $(function() { function render() { var tmpl = $('#group-tmpl').text(); $.get($.route('org.home.projects'), {}, function(data) { + var newGroup = []; + for(var i = 0, l = data.groups.length; i < l; i++) { + if (data.groups[i].type == 'user') { + var group = data.groups[i]; + for(var j = 0; j < group.projects.length; j++) { + if (group.projects[j].related) { + newGroup.push(group.projects[j]); + group.projects.splice(j, 1); + j --; + } + } + } + } + data.groups.push({ + type: 'tag', + projects: newGroup + }); data.groups.forEach(function (group) { group.name = NAME_MAP[group.type] || '其他'; - if (group.type == 'user') { - group.mine = true; - } }); var html = $.render(tmpl, data); $(".groups").html(html); @@ -523,4 +545,6 @@ $(function() { } render(); + $('.tip').tooltip(); + }); diff --git a/WebContent/org/home/index.vm b/WebContent/org/home/index.vm index 4a497b632..98fa98421 100644 --- a/WebContent/org/home/index.vm +++ b/WebContent/org/home/index.vm @@ -1,43 +1,52 @@ - + #parse('/tcom/template.rap.vm') 欢迎使用RAP + #includeNewRapStatic #bodyNewStart +
-

Dashboard

-
+

我的主页

+ +
加载中,请稍候
- - - - - - - #bodyNewStart -
- #bodyEnd - - - diff --git a/WebContent/platform/home.vm b/WebContent/platform/home.vm index 011ce062f..2e6fb49f5 100644 --- a/WebContent/platform/home.vm +++ b/WebContent/platform/home.vm @@ -1,9 +1,10 @@ - + #parse('/tcom/template.rap.vm') 欢迎使用RAP + #includeNewRapStatic + + + #bodyNewStart +
+

 RAP Dashboard

+
+
+

DEBUG INFO

+
$realtimeJSON
+
+
+
+
+

 实时数据

+
loading...
+
+
+
+
+

 趋势数据

+ + + +
+
+
+
+
+
+
+

 使用数据

+
+ 目前已有$modelLogMap.get("用户数").getValue() 位工程师
+ $modelLogMap.get("项目数").getValue() 个业务项目在使用RAP。
+ 在这里定义了 + $modelLogMap.get("接口数").getValue() 个接口
RAP已为小伙伴们伪造了
+ $modelLogMap.get("MOCK服务调用次数").getValue() 次MOCK数据! +
+
+
+
+ +
+

 今日统计

+ + + +
+
+
+ + + + + + + + + + #foreach($item in $logger.ipLog) + + + + + + #end + +
#IPCount
$velocityCount$item.key$item.value
+
+
+ + + + + + + + + + #foreach($item in $logger.userLog) + #if($item.key) + + + + + + #end + #end + +
#AccountCount
$velocityCount$item.key$item.value
+
+
+
+
+

 全量统计

+ + + +
+
+
+ + + + + + + + + + #foreach($item in $modelLog) + + + #if($item.title) + + #else + + #end + + + #end + +
#KeyCount
$velocityCount + +  $item.key + + $item.key$item.value
+
+
+
+
+
+ +
+ #bodyEnd + + + \ No newline at end of file diff --git a/WebContent/platform/monitor.js b/WebContent/platform/monitor.js new file mode 100644 index 000000000..ee1d37182 --- /dev/null +++ b/WebContent/platform/monitor.js @@ -0,0 +1,9 @@ +!function(){ + var data = window.logsData; + + console.log("IP Log"); + console.table(data.ipLog); + + console.log("USER Log"); + console.table(data.userLog); +}(); \ No newline at end of file diff --git a/WebContent/platform/monitor.vm b/WebContent/platform/monitor.vm new file mode 100644 index 000000000..138116425 --- /dev/null +++ b/WebContent/platform/monitor.vm @@ -0,0 +1,13 @@ + + + + RAP + + Hello World! + + + + + \ No newline at end of file diff --git a/WebContent/platform/status.vm b/WebContent/platform/status.vm deleted file mode 100644 index 05a80ee19..000000000 --- a/WebContent/platform/status.vm +++ /dev/null @@ -1,81 +0,0 @@ - -#parse('/tcom/template.rap.vm') - - - - RAP Status - #includeRapStatic - - - - #bodyStart -
-

level-1 TODO

-
* page level parallel lock & share
-
* last update history show
-
* User authentication & authorization
-
* Project data validation for input(basic) and automation(for specific automation func)
-

level-2 TODO

-
* action references action
-
* Email informing functionality
-
* project flow control with project stage and email informing
-
* Ordinary & Velocity automatically generation
-
* project stage management
-
* SVN mode
-
* page separate
-
* object order management
-

level-3 TODO

-
* full screen mode
-
* account&role management
-
* feedback module
-
* announcement on index page
-
* project data editing suggestions
-

bugs

-
* version switch should cause check in automatically
-
* make sure the order of objects updated consistent
-

history

-
* cache project data, optimize my project list and my project page [done] 9.15
-
* [bug] multi-mode share has a problem cause workspace & project level division [fixed] 9.15
-
* create accounts for FEs & RDs [done] 9.15
-
* auto complete on parameter input [done] 9.14
-
* pangu interface import(more than 3000 parameters, 80+ pages) [done] 9.14
-
* backup database [done] 9.13
-
* first real module-"customer info" imported [done] 9.13
-
* [bug] switch to added action after doAddEdit invoked [fixed] 9.13
-
* save the module tree state after page binding [done] 9.13
-
* autocomplete ui control [done] 9.9
-
* project member management [done] 9.9
-
* shortcut & view state compability of IE/Firefox [done] 9.9
-
* user input validation [done] 9.8
-
* tree parameters expand and shrink [done] 9.8
-
* json escape [done] 9.8
-
* version manage(VSS) [done] 9.7
-
* version observation & switch (VSS) [done] 9.7
-
* account manage [done] 9.6
-
* about rap page [done] 9.6
-
* login bug [done] 9.5
-
* [bug]tab shortcut will be make content lost[parameter-remark] [fixed] 9.9
-
* [bug]create first new module, than save, no module selected [fixed] 9.9
-
* SessionDestoryed Exception thrown [fixed] 9.6
-
* timer for session timeout delay[done] 9.6
-
- #bodyEnd - - diff --git a/WebContent/platform/test.vm b/WebContent/platform/test.vm index a0dafab7f..c2eaf9ba6 100644 --- a/WebContent/platform/test.vm +++ b/WebContent/platform/test.vm @@ -1,9 +1,10 @@ - + #parse('/tcom/template.rap.vm') RAP自动化测试套件 + #includeNewRapStatic @@ -20,10 +21,12 @@ + + - diff --git a/WebContent/project/myProjectList.vm b/WebContent/project/myProjectList.vm deleted file mode 100644 index 3e8a60fec..000000000 --- a/WebContent/project/myProjectList.vm +++ /dev/null @@ -1,126 +0,0 @@ - -#parse('/tcom/template.rap.vm') - - - - Project Manage - #includeRapStatic - - - - - #bodyStart - 创建新项目
-
- - - #set( $lstTitleList = [ - {"chn":"名称", "eval":'$item.name', "width":"300px"}, - {"chn":"创建日期", "eval":'
$item.createDateStr
', "width":"80px"}, - {"chn":"创建人", "eval":'
$item.user.name
', "width":"120px"}, - {"chn":"参与人", "eval":'$item.userListStrShort', "width":"310px"}, - {"chn":"操作", "eval":'
- #if($item.isManagable) - 编辑 - 删除 - #end -
', "width":"80px"} - ] ) - - #set( $fOptions = {"width":"940px", "url":"$projectUrl.myProjectList"} ) - - #table($lstTitleList $projectList $fOptions) -
-
-
- #bodyEnd - - #startFloater("floater" "" 600 350) -
- - - - - - - - - - - - - - - - - - - - #endFloater - - - - diff --git a/WebContent/stat/bootstrap3/css/bootstrap-theme.css b/WebContent/stat/bootstrap3/css/bootstrap-theme.css index a4069929b..f860bbc06 100644 --- a/WebContent/stat/bootstrap3/css/bootstrap-theme.css +++ b/WebContent/stat/bootstrap3/css/bootstrap-theme.css @@ -1,5 +1,5 @@ /*! - * Bootstrap v3.1.1 (http://getbootstrap.com) + * Bootstrap v3.2.0 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -36,6 +36,8 @@ .btn-default { text-shadow: 0 1px 0 #fff; background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -53,8 +55,15 @@ background-color: #e0e0e0; border-color: #dbdbdb; } +.btn-default:disabled, +.btn-default[disabled] { + background-color: #e0e0e0; + background-image: none; +} .btn-primary { background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); + background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -71,8 +80,15 @@ background-color: #2d6ca2; border-color: #2b669a; } +.btn-primary:disabled, +.btn-primary[disabled] { + background-color: #2d6ca2; + background-image: none; +} .btn-success { background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -89,8 +105,15 @@ background-color: #419641; border-color: #3e8f3e; } +.btn-success:disabled, +.btn-success[disabled] { + background-color: #419641; + background-image: none; +} .btn-info { background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -107,8 +130,15 @@ background-color: #2aabd2; border-color: #28a4c9; } +.btn-info:disabled, +.btn-info[disabled] { + background-color: #2aabd2; + background-image: none; +} .btn-warning { background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -125,8 +155,15 @@ background-color: #eb9316; border-color: #e38d13; } +.btn-warning:disabled, +.btn-warning[disabled] { + background-color: #eb9316; + background-image: none; +} .btn-danger { background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -143,6 +180,11 @@ background-color: #c12e2a; border-color: #b92c28; } +.btn-danger:disabled, +.btn-danger[disabled] { + background-color: #c12e2a; + background-image: none; +} .thumbnail, .img-thumbnail { -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); @@ -152,6 +194,8 @@ .dropdown-menu > li > a:focus { background-color: #e8e8e8; background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); background-repeat: repeat-x; @@ -161,12 +205,16 @@ .dropdown-menu > .active > a:focus { background-color: #357ebd; background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); background-repeat: repeat-x; } .navbar-default { background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -177,6 +225,8 @@ } .navbar-default .navbar-nav > .active > a { background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); + background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3)); background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); background-repeat: repeat-x; @@ -189,6 +239,8 @@ } .navbar-inverse { background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); @@ -196,6 +248,8 @@ } .navbar-inverse .navbar-nav > .active > a { background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); + background-image: -o-linear-gradient(top, #222 0%, #282828 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828)); background-image: linear-gradient(to bottom, #222 0%, #282828 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); background-repeat: repeat-x; @@ -218,6 +272,8 @@ } .alert-success { background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); background-repeat: repeat-x; @@ -225,6 +281,8 @@ } .alert-info { background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); background-repeat: repeat-x; @@ -232,6 +290,8 @@ } .alert-warning { background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); background-repeat: repeat-x; @@ -239,6 +299,8 @@ } .alert-danger { background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); background-repeat: repeat-x; @@ -246,40 +308,57 @@ } .progress { background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; } .progress-bar { background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); background-repeat: repeat-x; } .progress-bar-success { background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); background-repeat: repeat-x; } .progress-bar-info { background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); background-repeat: repeat-x; } .progress-bar-warning { background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); background-repeat: repeat-x; } .progress-bar-danger { background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); background-repeat: repeat-x; } +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} .list-group { border-radius: 4px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); @@ -290,6 +369,8 @@ .list-group-item.active:focus { text-shadow: 0 -1px 0 #3071a9; background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); background-repeat: repeat-x; @@ -301,42 +382,56 @@ } .panel-default > .panel-heading { background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); background-repeat: repeat-x; } .panel-primary > .panel-heading { background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); background-repeat: repeat-x; } .panel-success > .panel-heading { background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); background-repeat: repeat-x; } .panel-info > .panel-heading { background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); background-repeat: repeat-x; } .panel-warning > .panel-heading { background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); background-repeat: repeat-x; } .panel-danger > .panel-heading { background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); background-repeat: repeat-x; } .well { background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; diff --git a/WebContent/stat/bootstrap3/css/bootstrap-theme.css.map b/WebContent/stat/bootstrap3/css/bootstrap-theme.css.map index b36fc9a49..4cc41ab00 100644 --- a/WebContent/stat/bootstrap3/css/bootstrap-theme.css.map +++ b/WebContent/stat/bootstrap3/css/bootstrap-theme.css.map @@ -1 +1 @@ -{"version":3,"sources":["less/theme.less","less/mixins.less"],"names":[],"mappings":"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","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","//\n// Mixins\n// --------------------------------------------------\n\n\n// Utilities\n// -------------------------\n\n// Clearfix\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n\n// WebKit-style focus\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n\n// Center-align a block level element\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n\n// Sizing shortcuts\n.size(@width; @height) {\n width: @width;\n height: @height;\n}\n.square(@size) {\n .size(@size; @size);\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Text overflow\n// Requires inline-block or block for proper styling\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n\n\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Single side border-radius\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support the\n// standard `box-shadow` property.\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Transitions\n.transition(@transition) {\n -webkit-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n// Transformations\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n transform: rotate(@degrees);\n}\n.scale(@ratio; @ratio-y...) {\n -webkit-transform: scale(@ratio, @ratio-y);\n -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n transform: scale(@ratio, @ratio-y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n transform: translate(@x, @y);\n}\n.skew(@x; @y) {\n -webkit-transform: skew(@x, @y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n transform: skew(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// User select\n// For selecting text on the page\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n\n// Resize anything\n.resizable(@direction) {\n resize: @direction; // Options: horizontal, vertical, both\n overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Opacity\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n\n\n\n// GRADIENTS\n// --------------------------------------------------\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n\n// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n\n\n\n// Retina images\n//\n// Short retina mixin for setting background-image and -size\n\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n\n// Panels\n// -------------------------\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse .panel-body {\n border-top-color: @border;\n }\n }\n & > .panel-footer {\n + .panel-collapse .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n\n// Alerts\n// -------------------------\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n\n// Tables\n// -------------------------\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading { color: inherit; }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n\n// Button variants\n// -------------------------\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:hover,\n &:focus,\n &:active,\n &.active,\n .open .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 8%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n// -------------------------\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n\n// Pagination\n// -------------------------\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n\n// Labels\n// -------------------------\n.label-variant(@color) {\n background-color: @color;\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n\n// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n\n// Progress bars\n// -------------------------\n.progress-bar-variant(@color) {\n background-color: @color;\n .progress-striped & {\n #gradient > .striped();\n }\n}\n\n// Responsive utilities\n// -------------------------\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n\n\n// Grid System\n// -----------\n\n// Centered container element\n.container-fixed() {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n @media (min-width: @screen-xs-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-push(@columns) {\n @media (min-width: @screen-xs-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-pull(@columns) {\n @media (min-width: @screen-xs-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n\n// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-focus-border` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. ``\n// element gets special love because it's special, and that's a fact!\n\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Variables\n// --------------------------------------------------\n\n\n//== Colors\n//\n//## Gray and brand colors for use across Bootstrap.\n\n@gray-darker: lighten(#000, 13.5%); // #222\n@gray-dark: lighten(#000, 20%); // #333\n@gray: lighten(#000, 33.5%); // #555\n@gray-light: lighten(#000, 60%); // #999\n@gray-lighter: lighten(#000, 93.5%); // #eee\n\n@brand-primary: #428bca;\n@brand-success: #5cb85c;\n@brand-info: #5bc0de;\n@brand-warning: #f0ad4e;\n@brand-danger: #d9534f;\n\n\n//== Scaffolding\n//\n// ## Settings for some of the most global styles.\n\n//** Background color for ``.\n@body-bg: #fff;\n//** Global text color on ``.\n@text-color: @gray-dark;\n\n//** Global textual link color.\n@link-color: @brand-primary;\n//** Link hover color set via `darken()` function.\n@link-hover-color: darken(@link-color, 15%);\n\n\n//== Typography\n//\n//## Font, line-height, and color for body text, headings, and more.\n\n@font-family-sans-serif: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n@font-family-serif: Georgia, \"Times New Roman\", Times, serif;\n//** Default monospace fonts for ``, ``, and `
`.\n@font-family-monospace:   Menlo, Monaco, Consolas, \"Courier New\", monospace;\n@font-family-base:        @font-family-sans-serif;\n\n@font-size-base:          14px;\n@font-size-large:         ceil((@font-size-base * 1.25)); // ~18px\n@font-size-small:         ceil((@font-size-base * 0.85)); // ~12px\n\n@font-size-h1:            floor((@font-size-base * 2.6)); // ~36px\n@font-size-h2:            floor((@font-size-base * 2.15)); // ~30px\n@font-size-h3:            ceil((@font-size-base * 1.7)); // ~24px\n@font-size-h4:            ceil((@font-size-base * 1.25)); // ~18px\n@font-size-h5:            @font-size-base;\n@font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px\n\n//** Unit-less `line-height` for use in components like buttons.\n@line-height-base:        1.428571429; // 20/14\n//** Computed \"line-height\" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.\n@line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px\n\n//** By default, this inherits from the ``.\n@headings-font-family:    inherit;\n@headings-font-weight:    500;\n@headings-line-height:    1.1;\n@headings-color:          inherit;\n\n\n//-- Iconography\n//\n//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.\n\n@icon-font-path:          \"../fonts/\";\n@icon-font-name:          \"glyphicons-halflings-regular\";\n@icon-font-svg-id:        \"glyphicons_halflingsregular\";\n\n//== Components\n//\n//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).\n\n@padding-base-vertical:     6px;\n@padding-base-horizontal:   12px;\n\n@padding-large-vertical:    10px;\n@padding-large-horizontal:  16px;\n\n@padding-small-vertical:    5px;\n@padding-small-horizontal:  10px;\n\n@padding-xs-vertical:       1px;\n@padding-xs-horizontal:     5px;\n\n@line-height-large:         1.33;\n@line-height-small:         1.5;\n\n@border-radius-base:        4px;\n@border-radius-large:       6px;\n@border-radius-small:       3px;\n\n//** Global color for active items (e.g., navs or dropdowns).\n@component-active-color:    #fff;\n//** Global background color for active items (e.g., navs or dropdowns).\n@component-active-bg:       @brand-primary;\n\n//** Width of the `border` for generating carets that indicator dropdowns.\n@caret-width-base:          4px;\n//** Carets increase slightly in size for larger components.\n@caret-width-large:         5px;\n\n\n//== Tables\n//\n//## Customizes the `.table` component with basic values, each used across all table variations.\n\n//** Padding for `
';n+=""}n+="";if(_isEditMode){n+=getPTDHtml(e.id,'";for(var s=0;s"+(r?(new Array(r+1)).join("    "):"")+t+""}function remarkFilter(e){if(_isMockDisplay){return e}if(!e)return"";return e.replace(/[\s;]?@\w+=[^ ;]+[ ;]?/g,"")}function getEditInputHtml(e,t,n){return""}function getDataTypeEditSelectHtml(e,t){var n="",r=["","number","string","object","boolean","array","array","array","array"],i=r.length;n+="";return n}function getSavePanelHtml(e){if(e==null)return;var t=e.length,n="";t=t>=CONFIG.SAVE_LIST_MAX_LENGTH?CONFIG.SAVE_LIST_MAX_LENGTH:t;n+=TEMPLATE.SAVE_PANEL_BEGIN;for(var r=0;r"+(n?"新增存档":"存档:"+e.id+"      更新时间: "+e.updateDate)+"";return t}function getVersionPanelItemHtml(e){var t="";t+="";t+="";t+="";t+="";t+="";t+="";t+="";return t}rap.workspace=rap.workspace||{};var ws=rap.workspace,p=rap.project,util=rap.util,b=baidu,e=ecui,_curModuleId,_data,_curActionId,_isProcessing,_messageTimer,_messageContainerId,_sessionDelayTimer,_doesSoFarNoActionDisplay,_editContext,_isEditMode,_deletedObjectList,_viewState,_debugCounter,_isLocalStorageEnabled,_isMockDisplay,URL=null,MESSAGE={CONFIRM_COVER:"是否确定覆盖旧的内容?",CONFIRM_SAVE:"是否确认保存?",CONFIRM_CANCEL:"是否确定取消?",CONFIRM_CHECKIN:"是否确定提交?",CONFIRM_CHECKOUT:"是否确定获取?",CHECK_LOCK_CONFLICKTION:"正在为您检查工作区锁定状态...",CHECK_LOCK_CONFLICKTION_COMPLETED:"您已成功切换至编辑状态,该项目已被您锁定。",CHOOSE_AT_FIRST:"请先选择您要操作的选项.",SAVE_LIST_MAX_LENGTH_OVERFLOW:"您的存档空间已满,请删除不必要的存档,或覆盖旧的存档。",CONFIRM_DELETE:"您是否确认删除?",LOADING:"加载中...",LOAD:"已完成加载",MODULE_LOADING:"正在加载项目模块...",MODULE_LOAD:"项目模块加载完成",VERSION_LOADING:"正在请求版本信息...",VERSION_LOAD:"版本信息已加载",VERSION_EXIT:"已退出版本观看模式",VERSION_SWITCHING:"正在为您切换版本...",VERSION_SWITCHED:"版本切换成功",VERSION_SWITCH_ERROR:"版本切换中发生错误,已恢复至切换前",SAVING:"正在保存...",SAVED:"保存成功",DELETING:"正在删除...",DELETED:"删除成功",PROCESSING:"正在处理中,请稍后...",PROCESSED:"处理成功",ERROR:"出现错误,请稍后重试。",DO_NOT_DOUBLE_CLICK:"您的请求正在处理,请勿重复点击。",FATAL_ERROR:"发生严重错误,请联系维护人员并保留现场。",SESSION_DELAY_ERROR:"Session延时发生异常,建议您立即保存工作区并联系维护人员."},TEMPLATE={REQUEST_BEGIN:'

REQUEST PARAM LIST

项目名称 - -
项目成员 - -
项目介绍 - -
- - -
`s and ``s.\n@table-cell-padding: 8px;\n//** Padding for cells in `.table-condensed`.\n@table-condensed-cell-padding: 5px;\n\n//** Default background color used for all tables.\n@table-bg: transparent;\n//** Background color used for `.table-striped`.\n@table-bg-accent: #f9f9f9;\n//** Background color used for `.table-hover`.\n@table-bg-hover: #f5f5f5;\n@table-bg-active: @table-bg-hover;\n\n//** Border color for table and cell borders.\n@table-border-color: #ddd;\n\n\n//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n@btn-font-weight: normal;\n\n@btn-default-color: #333;\n@btn-default-bg: #fff;\n@btn-default-border: #ccc;\n\n@btn-primary-color: #fff;\n@btn-primary-bg: @brand-primary;\n@btn-primary-border: darken(@btn-primary-bg, 5%);\n\n@btn-success-color: #fff;\n@btn-success-bg: @brand-success;\n@btn-success-border: darken(@btn-success-bg, 5%);\n\n@btn-info-color: #fff;\n@btn-info-bg: @brand-info;\n@btn-info-border: darken(@btn-info-bg, 5%);\n\n@btn-warning-color: #fff;\n@btn-warning-bg: @brand-warning;\n@btn-warning-border: darken(@btn-warning-bg, 5%);\n\n@btn-danger-color: #fff;\n@btn-danger-bg: @brand-danger;\n@btn-danger-border: darken(@btn-danger-bg, 5%);\n\n@btn-link-disabled-color: @gray-light;\n\n\n//== Forms\n//\n//##\n\n//** `` background color\n@input-bg: #fff;\n//** `` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for ``s\n@input-color: @gray;\n//** `` border color\n@input-border: #ccc;\n//** `` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\n@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color: @gray-dark;\n@legend-border-color: #e5e5e5;\n\n//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\n\n@zindex-navbar: 1000;\n@zindex-dropdown: 1000;\n@zindex-popover: 1010;\n@zindex-tooltip: 1030;\n@zindex-navbar-fixed: 1030;\n@zindex-modal-background: 1040;\n@zindex-modal: 1050;\n\n\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\n@navbar-border-radius: @border-radius-base;\n@navbar-padding-horizontal: floor((@grid-gutter-width / 2));\n@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);\n@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\n\n// Navbar links\n@navbar-default-link-color: #777;\n@navbar-default-link-hover-color: #333;\n@navbar-default-link-hover-bg: transparent;\n@navbar-default-link-active-color: #555;\n@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);\n@navbar-default-link-disabled-color: #ccc;\n@navbar-default-link-disabled-bg: transparent;\n\n// Navbar brand label\n@navbar-default-brand-color: @navbar-default-link-color;\n@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);\n@navbar-default-brand-hover-bg: transparent;\n\n// Navbar toggle\n@navbar-default-toggle-hover-bg: #ddd;\n@navbar-default-toggle-icon-bar-bg: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n\n// Inverted navbar\n// Reset inverted navbar basics\n@navbar-inverse-color: @gray-light;\n@navbar-inverse-bg: #222;\n@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color: @gray-light;\n@navbar-inverse-link-hover-color: #fff;\n@navbar-inverse-link-hover-bg: transparent;\n@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;\n@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-link-disabled-color: #444;\n@navbar-inverse-link-disabled-bg: transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color: @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color: #fff;\n@navbar-inverse-brand-hover-bg: transparent;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg: #333;\n@navbar-inverse-toggle-icon-bar-bg: #fff;\n@navbar-inverse-toggle-border-color: #333;\n\n\n//== Navs\n//\n//##\n\n//=== Shared nav styles\n@nav-link-padding: 10px 15px;\n@nav-link-hover-bg: @gray-lighter;\n\n@nav-disabled-link-color: @gray-light;\n@nav-disabled-link-hover-color: @gray-light;\n\n@nav-open-link-hover-color: #fff;\n\n//== Tabs\n@nav-tabs-border-color: #ddd;\n\n@nav-tabs-link-hover-border-color: @gray-lighter;\n\n@nav-tabs-active-link-hover-bg: @body-bg;\n@nav-tabs-active-link-hover-color: @gray;\n@nav-tabs-active-link-hover-border-color: #ddd;\n\n@nav-tabs-justified-link-border-color: #ddd;\n@nav-tabs-justified-active-link-border-color: @body-bg;\n\n//== Pills\n@nav-pills-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: fadein(@popover-border-color, 5%);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);\n\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\n\n@alert-padding: 15px;\n@alert-border-radius: @border-radius-base;\n@alert-link-font-weight: bold;\n\n@alert-success-bg: @state-success-bg;\n@alert-success-text: @state-success-text;\n@alert-success-border: @state-success-border;\n\n@alert-info-bg: @state-info-bg;\n@alert-info-text: @state-info-text;\n@alert-info-border: @state-info-border;\n\n@alert-warning-bg: @state-warning-bg;\n@alert-warning-text: @state-warning-text;\n@alert-warning-border: @state-warning-border;\n\n@alert-danger-bg: @state-danger-bg;\n@alert-danger-text: @state-danger-text;\n@alert-danger-border: @state-danger-border;\n\n\n//== Progress bars\n//\n//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\n@panel-footer-bg: #f5f5f5;\n\n@panel-default-text: @gray-dark;\n@panel-default-border: #ddd;\n@panel-default-heading-bg: #f5f5f5;\n\n@panel-primary-text: #fff;\n@panel-primary-border: @brand-primary;\n@panel-primary-heading-bg: @brand-primary;\n\n@panel-success-text: @state-success-text;\n@panel-success-border: @state-success-border;\n@panel-success-heading-bg: @state-success-bg;\n\n@panel-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-bg;\n\n@panel-warning-text: @state-warning-text;\n@panel-warning-border: @state-warning-border;\n@panel-warning-heading-bg: @state-warning-bg;\n\n@panel-danger-text: @state-danger-text;\n@panel-danger-border: @state-danger-border;\n@panel-danger-heading-bg: @state-danger-bg;\n\n\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\n@badge-active-bg: #fff;\n\n@badge-font-weight: bold;\n@badge-line-height: 1;\n@badge-border-radius: 10px;\n\n\n//== Breadcrumbs\n//\n//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n\n//== Carousel\n//\n//##\n\n@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);\n\n@carousel-control-color: #fff;\n@carousel-control-width: 15%;\n@carousel-control-opacity: .5;\n@carousel-control-font-size: 20px;\n\n@carousel-indicator-active-bg: #fff;\n@carousel-indicator-border-color: #fff;\n\n@carousel-caption-color: #fff;\n\n\n//== Close\n//\n//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote font size\n@blockquote-font-size: (@font-size-base * 1.25);\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n }\n\n > .active,\n > .next,\n > .prev { display: block; }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: none;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n margin-left: -10px;\n font-family: serif;\n }\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n margin-left: -15px;\n font-size: 30px;\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 200;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall,\n.small { font-size: 85%; }\n\n// Undo browser default styling\ncite { font-style: normal; }\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: @grid-float-breakpoint) {\n .dl-horizontal {\n dt {\n float: left;\n width: (@component-offset-horizontal - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @component-offset-horizontal;\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n white-space: nowrap;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n max-width: 100%;\n background-color: @table-bg;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\n }\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n@media (max-width: @screen-xs-max) {\n .table-responsive {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: scroll;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; /* IE8-9 */\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n cursor: not-allowed;\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\n\ninput[type=\"date\"] {\n line-height: @input-height-base;\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n display: block;\n min-height: @line-height-computed; // clear the floating input if there is no label text\n margin-top: 10px;\n margin-bottom: 10px;\n padding-left: 20px;\n label {\n display: inline;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n float: left;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n\n // Feedback icon (requires .glyphicon classes)\n .form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n }\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n margin-bottom: 0; // Remove default margin from `p`\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match (which also avoids\n // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n vertical-align: middle;\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n float: none;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of labels, radios, and checkboxes\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n .form-control-static {\n padding-top: (@padding-base-vertical + 1);\n }\n\n // Only right align form labels here when the columns stop stacking\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n pointer-events: none; // Future-proof disabling of clicks\n .opacity(.65);\n .box-shadow(none);\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n cursor: pointer;\n border-radius: 0;\n\n &,\n &:active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n padding-left: 0;\n padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n &:focus {\n // Remove focus outline when dropdown JS adds it after closing the menu\n outline: none;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n}\n\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n display: none;\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n &.in {\n display: block;\n }\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition(height .35s ease);\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot')\";\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.woff') format('woff')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg')\";\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base solid;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: not-allowed;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base solid;\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 1px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn { .input-lg(); }\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn { .input-sm(); }\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n max-height: @navbar-collapse-max-height;\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: none;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\n }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: not-allowed;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n &[href] {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\n }\n}\n\n// Hover state, but only for links\na.badge {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n > .pull-left {\n margin-right: 10px;\n }\n > .pull-right {\n margin-left: 10px;\n }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on
    ,
      , or
      .\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n\n // Align badges within list items\n > .badge {\n float: right;\n }\n > .badge + .badge {\n margin-right: 5px;\n }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @list-group-hover-bg;\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: 10px 15px;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table {\n margin-bottom: 0;\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n overflow: hidden; // crop contents when collapsed\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n + .panel-collapse .panel-body {\n border-top: 1px solid @panel-inner-border;\n }\n }\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n display: none;\n overflow: auto;\n overflow-y: scroll;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0)}\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: none;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n margin-top: 15px;\n padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n visibility: visible;\n font-size: @font-size-small;\n line-height: 1.4;\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n text-decoration: none;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n text-align: left; // Reset given new insertion method\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Overrides for proper insertion\n white-space: normal;\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 18px;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#browsers\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"bootstrap.css","sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"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;EAAW,kBAAA;EHoR9C;AGnRmC;EAAW,kBAAA;EHsR9C;AGrRmC;EAAW,kBAAA;EHwR9C;AGvRmC;EAAW,kBAAA;EH0R9C;AGzRmC;EAAW,kBAAA;EH4R9C;AG3RmC;EAAW,kBAAA;EH8R9C;AG7RmC;EAAW,kBAAA;EHgS9C;AG/RmC;EAAW,kBAAA;EHkS9C;AGjSmC;EAAW,kBAAA;EHoS9C;AGnSmC;EAAW,kBAAA;EHsS9C;AGrSmC;EAAW,kBAAA;EHwS9C;AGvSmC;EAAW,kBAAA;EH0S9C;AGzSmC;EAAW,kBAAA;EH4S9C;AG3SmC;EAAW,kBAAA;EH8S9C;AG7SmC;EAAW,kBAAA;EHgT9C;AG/SmC;EAAW,kBAAA;EHkT9C;AGjTmC;EAAW,kBAAA;EHoT9C;AGnTmC;EAAW,kBAAA;EHsT9C;AGrTmC;EAAW,kBAAA;EHwT9C;AGvTmC;EAAW,kBAAA;EH0T9C;AGzTmC;EAAW,kBAAA;EH4T9C;AG3TmC;EAAW,kBAAA;EH8T9C;AG7TmC;EAAW,kBAAA;EHgU9C;AG/TmC;EAAW,kBAAA;EHkU9C;AGjUmC;EAAW,kBAAA;EHoU9C;AGnUmC;EAAW,kBAAA;EHsU9C;AGrUmC;EAAW,kBAAA;EHwU9C;AGvUmC;EAAW,kBAAA;EH0U9C;AGzUmC;EAAW,kBAAA;EH4U9C;AG3UmC;EAAW,kBAAA;EH8U9C;AG7UmC;EAAW,kBAAA;EHgV9C;AG/UmC;EAAW,kBAAA;EHkV9C;AGjVmC;EAAW,kBAAA;EHoV9C;AGnVmC;EAAW,kBAAA;EHsV9C;AGrVmC;EAAW,kBAAA;EHwV9C;AGvVmC;EAAW,kBAAA;EH0V9C;AGzVmC;EAAW,kBAAA;EH4V9C;AG3VmC;EAAW,kBAAA;EH8V9C;AG7VmC;EAAW,kBAAA;EHgW9C;AG/VmC;EAAW,kBAAA;EHkW9C;AGjWmC;EAAW,kBAAA;EHoW9C;AGnWmC;EAAW,kBAAA;EHsW9C;AGrWmC;EAAW,kBAAA;EHwW9C;AGvWmC;EAAW,kBAAA;EH0W9C;AGzWmC;EAAW,kBAAA;EH4W9C;AG3WmC;EAAW,kBAAA;EH8W9C;AG7WmC;EAAW,kBAAA;EHgX9C;AG/WmC;EAAW,kBAAA;EHkX9C;AGjXmC;EAAW,kBAAA;EHoX9C;AGnXmC;EAAW,kBAAA;EHsX9C;AGrXmC;EAAW,kBAAA;EHwX9C;AGvXmC;EAAW,kBAAA;EH0X9C;AGzXmC;EAAW,kBAAA;EH4X9C;AG3XmC;EAAW,kBAAA;EH8X9C;AG7XmC;EAAW,kBAAA;EHgY9C;AG/XmC;EAAW,kBAAA;EHkY9C;AGjYmC;EAAW,kBAAA;EHoY9C;AGnYmC;EAAW,kBAAA;EHsY9C;AGrYmC;EAAW,kBAAA;EHwY9C;AGvYmC;EAAW,kBAAA;EH0Y9C;AGzYmC;EAAW,kBAAA;EH4Y9C;AG3YmC;EAAW,kBAAA;EH8Y9C;AG7YmC;EAAW,kBAAA;EHgZ9C;AG/YmC;EAAW,kBAAA;EHkZ9C;AGjZmC;EAAW,kBAAA;EHoZ9C;AGnZmC;EAAW,kBAAA;EHsZ9C;AGrZmC;EAAW,kBAAA;EHwZ9C;AGvZmC;EAAW,kBAAA;EH0Z9C;AGzZmC;EAAW,kBAAA;EH4Z9C;AG3ZmC;EAAW,kBAAA;EH8Z9C;AG7ZmC;EAAW,kBAAA;EHga9C;AG/ZmC;EAAW,kBAAA;EHka9C;AGjamC;EAAW,kBAAA;EHoa9C;AGnamC;EAAW,kBAAA;EHsa9C;AGramC;EAAW,kBAAA;EHwa9C;AGvamC;EAAW,kBAAA;EH0a9C;AGzamC;EAAW,kBAAA;EH4a9C;AG3amC;EAAW,kBAAA;EH8a9C;AG7amC;EAAW,kBAAA;EHgb9C;AG/amC;EAAW,kBAAA;EHkb9C;AGjbmC;EAAW,kBAAA;EHob9C;AGnbmC;EAAW,kBAAA;EHsb9C;AGrbmC;EAAW,kBAAA;EHwb9C;AGvbmC;EAAW,kBAAA;EH0b9C;AGzbmC;EAAW,kBAAA;EH4b9C;AG3bmC;EAAW,kBAAA;EH8b9C;AG7bmC;EAAW,kBAAA;EHgc9C;AG/bmC;EAAW,kBAAA;EHkc9C;AGjcmC;EAAW,kBAAA;EHoc9C;AGncmC;EAAW,kBAAA;EHsc9C;AGrcmC;EAAW,kBAAA;EHwc9C;AGvcmC;EAAW,kBAAA;EH0c9C;AGzcmC;EAAW,kBAAA;EH4c9C;AG3cmC;EAAW,kBAAA;EH8c9C;AG7cmC;EAAW,kBAAA;EHgd9C;AG/cmC;EAAW,kBAAA;EHkd9C;AGjdmC;EAAW,kBAAA;EHod9C;AGndmC;EAAW,kBAAA;EHsd9C;AGrdmC;EAAW,kBAAA;EHwd9C;AGvdmC;EAAW,kBAAA;EH0d9C;AGzdmC;EAAW,kBAAA;EH4d9C;AG3dmC;EAAW,kBAAA;EH8d9C;AG7dmC;EAAW,kBAAA;EHge9C;AG/dmC;EAAW,kBAAA;EHke9C;AGjemC;EAAW,kBAAA;EHoe9C;AGnemC;EAAW,kBAAA;EHse9C;AGremC;EAAW,kBAAA;EHwe9C;AGvemC;EAAW,kBAAA;EH0e9C;AGzemC;EAAW,kBAAA;EH4e9C;AG3emC;EAAW,kBAAA;EH8e9C;AG7emC;EAAW,kBAAA;EHgf9C;AG/emC;EAAW,kBAAA;EHkf9C;AGjfmC;EAAW,kBAAA;EHof9C;AGnfmC;EAAW,kBAAA;EHsf9C;AGrfmC;EAAW,kBAAA;EHwf9C;AGvfmC;EAAW,kBAAA;EH0f9C;AGzfmC;EAAW,kBAAA;EH4f9C;AG3fmC;EAAW,kBAAA;EH8f9C;AG7fmC;EAAW,kBAAA;EHggB9C;AG/fmC;EAAW,kBAAA;EHkgB9C;AGjgBmC;EAAW,kBAAA;EHogB9C;AGngBmC;EAAW,kBAAA;EHsgB9C;AGrgBmC;EAAW,kBAAA;EHwgB9C;AGvgBmC;EAAW,kBAAA;EH0gB9C;AGzgBmC;EAAW,kBAAA;EH4gB9C;AG3gBmC;EAAW,kBAAA;EH8gB9C;AG7gBmC;EAAW,kBAAA;EHghB9C;AG/gBmC;EAAW,kBAAA;EHkhB9C;AGjhBmC;EAAW,kBAAA;EHohB9C;AGnhBmC;EAAW,kBAAA;EHshB9C;AGrhBmC;EAAW,kBAAA;EHwhB9C;AGvhBmC;EAAW,kBAAA;EH0hB9C;AGzhBmC;EAAW,kBAAA;EH4hB9C;AG3hBmC;EAAW,kBAAA;EH8hB9C;AG7hBmC;EAAW,kBAAA;EHgiB9C;AG/hBmC;EAAW,kBAAA;EHkiB9C;AGjiBmC;EAAW,kBAAA;EHoiB9C;AGniBmC;EAAW,kBAAA;EHsiB9C;AGriBmC;EAAW,kBAAA;EHwiB9C;AGviBmC;EAAW,kBAAA;EH0iB9C;AGziBmC;EAAW,kBAAA;EH4iB9C;AG3iBmC;EAAW,kBAAA;EH8iB9C;AG7iBmC;EA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A;Efk8CH;Ae97CC;EACE,YAAA;Efg8CH;Ael7CC;EACE,mBAAA;Efo7CH;Aer7CC;EACE,2BAAA;Efu7CH;Aex7CC;EACE,2BAAA;Ef07CH;Ae37CC;EACE,kBAAA;Ef67CH;Ae97CC;EACE,2BAAA;Efg8CH;Aej8CC;EACE,2BAAA;Efm8CH;Aep8CC;EACE,kBAAA;Efs8CH;Aev8CC;EACE,2BAAA;Efy8CH;Ae18CC;EACE,2BAAA;Ef48CH;Ae78CC;EACE,kBAAA;Ef+8CH;Aeh9CC;EACE,2BAAA;Efk9CH;Aen9CC;EACE,0BAAA;Efq9CH;Aet9CC;EACE,iBAAA;Efw9CH;Aa59CD;EE9BI;IACE,aAAA;If6/CH;Eet/CD;IACE,aAAA;Ifw/CD;Eez/CD;IACE,qBAAA;If2/CD;Ee5/CD;IACE,qBAAA;If8/CD;Ee//CD;IACE,YAAA;IfigDD;EelgDD;IACE,qBAAA;IfogDD;EergDD;IACE,qBAAA;IfugDD;EexgDD;IACE,YAAA;If0gDD;Ee3gDD;IACE,qBAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,YAAA;IfmhDD;EephDD;IACE,qBAAA;IfshDD;EevhDD;IACE,oBAAA;IfyhDD;Ee3gDD;IACE,aAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,qBAAA;IfmhDD;EephDD;IACE,YAAA;IfshDD;EevhDD;IACE,qBAAA;IfyhDD;Ee1hDD;IACE,qBAAA;If4hDD;Ee7hDD;IACE,YAAA;If+hDD;EehiDD;IACE,qBAAA;IfkiDD;EeniDD;IACE,qBAAA;IfqiDD;EetiDD;IACE,YAAA;IfwiDD;EeziDD;IACE,qBAAA;If2iDD;Ee5iDD;IACE,oBAAA;If8iDD;Ee1iDD;IACE,aAAA;If4iDD;Ee5jDD;IACE,YAAA;If8jDD;Ee/jDD;IACE,oBAAA;IfikDD;EelkDD;IACE,oBAAA;IfokDD;EerkDD;IACE,WAAA;IfukDD;EexkDD;IACE,oBAAA;If0kDD;Ee3kDD;IACE,oBAAA;If6kDD;Ee9kDD;IACE,WAAA;IfglDD;EejlDD;IACE,oBAAA;IfmlDD;EeplDD;IACE,oBAAA;IfslDD;EevlDD;IACE,WAAA;IfylDD;Ee1lDD;IACE,oBAAA;If4lDD;Ee7lDD;IACE,mBAAA;If+lDD;Ee3lDD;IACE,YAAA;If6lDD;Ee/kDD;IACE,mBAAA;IfilDD;EellDD;IACE,2BAAA;IfolDD;EerlDD;IACE,2BAAA;IfulDD;EexlDD;IACE,kBAAA;If0lDD;Ee3lDD;IACE,2BAAA;If6lDD;Ee9lDD;IACE,2BAAA;IfgmDD;EejmDD;IACE,kBAAA;IfmmDD;EepmDD;IACE,2BAAA;IfsmDD;EevmDD;IACE,2BAAA;IfymDD;Ee1mDD;IACE,kBAAA;If4mDD;Ee7mDD;IACE,2BAAA;If+mDD;EehnDD;IACE,0BAAA;IfknDD;EennDD;IACE,iBAAA;IfqnDD;EACF;AajnDD;EEvCI;IACE,aAAA;If2pDH;EeppDD;IACE,aAAA;IfspDD;EevpDD;IACE,qBAAA;IfypDD;Ee1pDD;IACE,qBAAA;If4pDD;Ee7pDD;IACE,YAAA;If+pDD;EehqDD;IACE,qBAAA;IfkqDD;EenqDD;IACE,qBAAA;IfqqDD;EetqDD;IACE,YAAA;IfwqDD;EezqDD;IACE,qBAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,YAAA;IfirDD;EelrDD;IACE,qBAAA;IforDD;EerrDD;IACE,oBAAA;IfurDD;EezqDD;IACE,aAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,qBAAA;IfirDD;EelrDD;IACE,YAAA;IforDD;EerrDD;IACE,qBAAA;IfurDD;EexrDD;IACE,qBAAA;If0rDD;Ee3rDD;IACE,YAAA;If6rDD;Ee9rDD;IACE,qBAAA;IfgsDD;EejsDD;IACE,qBAAA;IfmsDD;EepsDD;IACE,YAAA;IfssDD;EevsDD;IACE,qBAAA;IfysDD;Ee1sDD;IACE,oBAAA;If4sDD;EexsDD;IACE,aAAA;If0sDD;Ee1tDD;IACE,YAAA;If4tDD;Ee7tDD;IACE,oBAAA;If+tDD;EehuDD;IACE,oBAAA;IfkuDD;EenuDD;IACE,WAAA;IfquDD;EetuDD;IACE,oBAAA;IfwuDD;EezuDD;IACE,oBAAA;If2uDD;Ee5uDD;IACE,WAAA;If8uDD;Ee/uDD;IACE,oBAAA;IfivDD;EelvDD;IACE,oBAAA;IfovDD;EervDD;IACE,WAAA;IfuvDD;EexvDD;IACE,oBAAA;If0vDD;Ee3vDD;IACE,mBAAA;If6vDD;EezvDD;IACE,YAAA;If2vDD;Ee7uDD;IACE,mBAAA;If+uDD;EehvDD;IACE,2BAAA;IfkvDD;EenvDD;IACE,2BAAA;IfqvDD;EetvDD;IACE,kBAAA;IfwvDD;EezvDD;IACE,2BAAA;If2vDD;Ee5vDD;IACE,2BAAA;If8vDD;Ee/vDD;IACE,kBAAA;IfiwDD;EelwDD;IACE,2BAAA;IfowDD;EerwDD;IACE,2BAAA;IfuwDD;EexwDD;IACE,kBAAA;If0wDD;Ee3wDD;IACE,2BAAA;If6wDD;Ee9wDD;IACE,0BAAA;IfgxDD;EejxDD;IACE,iBAAA;IfmxDD;EACF;AaxwDD;EE9CI;IACE,aAAA;IfyzDH;EelzDD;IACE,aAAA;IfozDD;EerzDD;IACE,qBAAA;IfuzDD;EexzDD;IACE,qBAAA;If0zDD;Ee3zDD;IACE,YAAA;If6zDD;Ee9zDD;IACE,qBAAA;Ifg0DD;Eej0DD;IACE,qBAAA;Ifm0DD;Eep0DD;IACE,YAAA;Ifs0DD;Eev0DD;IACE,qBAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,YAAA;If+0DD;Eeh1DD;IACE,qBAAA;Ifk1DD;Een1DD;IACE,oBAAA;Ifq1DD;Eev0DD;IACE,aAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,qBAAA;If+0DD;Eeh1DD;IACE,YAAA;Ifk1DD;Een1DD;IACE,qBAAA;Ifq1DD;Eet1DD;IACE,qBAAA;Ifw1DD;Eez1DD;IACE,YAAA;If21DD;Ee51DD;IACE,qBAAA;If81DD;Ee/1DD;IACE,qBAAA;Ifi2DD;Eel2DD;IACE,YAAA;Ifo2DD;Eer2DD;IACE,qBAAA;Ifu2DD;Eex2DD;IACE,oBAAA;If02DD;Eet2DD;IACE,aAAA;Ifw2DD;Eex3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AAA;EACI,uBAAA;ErBqsFT;AoB9qFD;EClBI,gBAAA;EACA,2BAAA;ErBmsFH;AoB/qFD;ECrDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBuuFD;AqBruFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBuuFP;AqBruFC;;;EAGE,wBAAA;ErBuuFH;AqBluFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErB8uFT;AoBptFD;ECrBI,gBAAA;EACA,2BAAA;ErB4uFH;AoBptFD;ECzDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBgxFD;AqB9wFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBgxFP;AqB9wFC;;;EAGE,wBAAA;ErBgxFH;AqB3wFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBuxFT;AoBzvFD;ECzBI,gBAAA;EACA,2BAAA;ErBqxFH;AoBzvFD;EC7DE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErByzFD;AqBvzFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErByzFP;AqBvzFC;;;EAGE,wBAAA;ErByzFH;AqBpzFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBg0FT;AoB9xFD;EC7BI,gBAAA;EACA,2BAAA;ErB8zFH;AoB9xFD;ECjEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBk2FD;AqBh2FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBk2FP;AqBh2FC;;;EAGE,wBAAA;ErBk2FH;AqB71FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBy2FT;AoBn0FD;ECjCI,gBAAA;EACA,2BAAA;ErBu2FH;AoBn0FD;ECrEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB24FD;AqBz4FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB24FP;AqBz4FC;;;EAGE,wBAAA;ErB24FH;AqBt4FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBk5FT;AoBx2FD;ECrCI,gBAAA;EACA,2BAAA;ErBg5FH;AoBn2FD;EACE,gBAAA;EACA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","sourcesContent":[null,"/*! normalize.css v3.0.1 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n// user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n// (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; // 2\n box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n * {\n text-shadow: none !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n background: transparent !important;\n box-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links for images, or javascript/internal links\n a[href^=\"javascript:\"]:after,\n a[href^=\"#\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\n }\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .table {\n td,\n th {\n background-color: #fff !important;\n }\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n width: 100% \\9; // Force IE10 and below to size SVG images correctly\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\n// Undo browser default styling\ncite {\n font-style: normal;\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @grid-float-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\n }\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: auto;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n cursor: not-allowed;\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned.\n// As a workaround, we set a pixel line-height that matches the\n// given height of the input. Since this fucks up everything else, we have to\n// appropriately reset it for Internet Explorer and the size variations.\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n line-height: @input-height-base;\n // IE8+ misaligns the text within date inputs, so we reset\n line-height: @line-height-base ~\"\\0\";\n\n &.input-sm {\n line-height: @input-height-small;\n }\n &.input-lg {\n line-height: @input-height-large;\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n min-height: @line-height-computed; // clear the floating input if there is no label text\n margin-top: 10px;\n margin-bottom: 10px;\n\n label {\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because
";if(i>0){n+="
";if(_isEditMode){n+=""}else{n+=util.escaper.escapeInH(t)}n+="
"+e.version+""+util.escaper.escapeInH(e.userName)+""+e.createDateStr+""+util.escaper.escapeInH(e.description)+"
',REQUEST_BEGIN_EDIT:'

REQUEST PARAM LIST

变量名含义类型备注
',REQUEST_END:"
OP变量名含义类型备注
",REQUEST_PARAMETER_ADD_BUTTON:'',RESPONSE_BEGIN:'

RESPONSE PARAM LIST

',RESPONSE_BEGIN_EDIT:'

RESPONSE PARAM LIST

变量名含义类型备注
',RESPONSE_END:"
OP变量名含义类型备注
",RESPONSE_PARAMETER_ADD_BUTTON:'',SAVE_PANEL_BEGIN:'
',SAVE_PANEL_END:"
",VERSION_PANEL_BEGIN:"
",VERSION_PANEL_END:"
OP版本操作人操作时间描述
",MODULE_ADD_BUTTON:'',SEPERATOR:'
',NO_DATA_CHECKED:"
没有可获取或更新的数据
"},CONFIG={SAVE_LIST_MAX_LENGTH:10,DEFAULT_MAX_LENGTH:50,REMARK_MAX_LENGTH:9999,DEFAULT_INPUT_WIDTH:100,MODULE_NAME_WIDTH:100,PARAMETER_NAME_WIDTH:160,PARAMETER_IDENTIFIER_WIDTH:160,PARAMETER_TYPE_WIDTH:110,PARAMETER_REMARK_WIDTH:300,MESSAGE_TIMEOUT:5e3,SESSION_DELAY_TIMESPAN:3e5,KEYPRESS_EVENT_NAME:baidu.browser.firefox?"keypress":"keydown"},CONST={WARN:"warn",ERROR:"error",LOADING:"loading",LOAD:"load",NORMAL:"normal",EDIT:"edit",VERSION:"version"},ELEMENT_ID={SAVE_PANEL:"saveFloater",SAVE_PANEL_CONTENT:"div-save-floater-content",SAVE_PANEL_MESSAGE:"div-save-floater-message",VERSION_PANEL:"versionFloater",VERSION_PANEL_MESSAGE:"div-version-floater-message",VERSION_PANEL_CONTENT:"div-version-floater-content",CHECKOUT_PANEL:"checkoutFloater",CHECKOUT_PANEL_CONTENT:"div-checkout-floater-content",CHECKOUT_PANEL_MESSAGE:"div-checkout-floater-message",CHECKIN_PANEL:"checkinFloater",CHECKIN_PANEL_CONTENT:"div-checkin-floater-content",CHECKIN_PANEL_MESSAGE:"div-checkin-floater-message",VSS_PANEL_MESSAGE:"div-saveVSS-floater-message",WORKSPACE_MESSAGE:"div-w-message",EDIT_INPUT:"txtMTName",IMPORT_JSON_MESSAGE:"div-importJSON-floater-message"},PREFIX={SAVE:"radio-save-"};ws.init=function(e,t){_isLocalStorageEnabled=typeof localStorage!="undefined";_isMockDisplay=false;URL=t;try{_data=e;_data.projectDataOriginal=b.object.clone(_data.projectData)}catch(n){showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.FATAL_ERROR)}b.dom.ready(function(){_sessionDelayTimer=setInterval(sessionDelay,CONFIG.SESSION_DELAY_TIMESPAN);_viewState={moduleId:-1,pageId:-1,actionId:-1,parameterId:-1};_debugCounter=1;window.onbeforeunload=function(){if(_isEditMode){if(_isLocalStorageEnabled){localStorage.setItem("_data",b.json.stringify(_data))}return"现在退出所有修改都将丢失,确认退出?"}};bind();ecui.ui.Tree.prototype.onclick=function(e){return e.target==this.getBase()}})};ws._getData=function(){return _data};ws.switchM=function(e){if(e<0){setEmptyView(true);return}var t=getDiv(_curModuleId,"m"),n=getDiv(_curModuleId,"mt"),r=getDiv(e,"m"),i=getDiv(e,"mt");if(r&&i){if(t&&n){t.style.display="";b.dom.removeClass(n,"cur")}r.style.display="block";b.dom.addClass(i,"cur")}_curModuleId=e;switchToCurA()};ws.switchA=function(e,t){if(!t){if(!p.isActionInModule(e,_curModuleId))return}var n=p.getAction(e);if(n==null)return;getDiv(_curModuleId,"a").innerHTML=getAHtml(n);renderA();_curActionId=e};ws.addM=function(){var e=b.g("div-m-list"),t=b.g("div-mt-list"),n=p.addModule(),r=p.getModule(n);if(isEditing()){cancelEdit()}if(p.getModuleList().length==1){setEmptyView(false,n)}e.innerHTML+=getMHtml(r);b.dom.insertHTML("div-add-m","beforeBegin",getMTHtml(r));ws.switchM(n);ws.edit(n,"mt")};ws.addParam=function(e,t){var n=-1;if(e=="child"){n=p.addChildParameter(t)}else if(e=="request"){n=p.addRequestParameter(_curActionId)}else if(e=="response"){n=p.addResponseParameter(_curActionId)}else{throw new Error("unkown type: "+e+" in ws.addParam(type, parentParamId);")}this.finishEdit();this.switchA(_curActionId);if(n>0){this.edit(n,"param-identifier")}};ws.removeM=function(){if(!confirm(MESSAGE.CONFIRM_DELETE))return;if(p.isEmpty())return;if(isEditing())cancelEdit();p.removeModule(_curModuleId);putObjectIntoDeletedPool("Module",_curModuleId);b.dom.remove(getDiv(_curModuleId,"m"));var t=b.dom.getAncestorByTag(getDivId(_curModuleId,"mt"),"a");e.dom.remove(t);var n=p.getModuleList();if(!n||n.length==0){setEmptyView(true)}else{ws.switchM(n[n.length-1].id)}};ws.removeA=function(e){if(!confirm(MESSAGE.CONFIRM_DELETE))return;p.removeAction(e);putObjectIntoDeletedPool("Action",e);b.dom.remove(b.g("div-a-tree-node-"+e));if(e==_curActionId){switchToCurA()}};ws.removeP=function(e){if(!confirm(MESSAGE.CONFIRM_DELETE))return;p.removePage(e);putObjectIntoDeletedPool("Page",e);updateCurMTree()};ws.removeParam=function(e){p.removeParameter(e);putObjectIntoDeletedPool("Parameter",e);ws.switchA(_curActionId)};ws.edit=function(e,t){var n,r="",i,s=CONFIG.DEFAULT_INPUT_WIDTH;if(!_isEditMode||t=="param-op"){return}if(isEditing()){if(_editContext.id==e&&_editContext.key==t){return}else{this.finishEdit()}}switch(t){case"mt":s=CONFIG.MODULE_NAME_WIDTH;n=getDiv(e,t);i=b.trim(n.innerHTML);r+=getEditInputHtml(i,s,CONFIG.DEFAULT_MAX_LENGTH);break;case"param-name":s=CONFIG.PARAMETER_NAME_WIDTH;n=getTd(e,t);i=b.trim(n.innerHTML);r+=getEditInputHtml(i,s,CONFIG.DEFAULT_MAX_LENGTH);break;case"param-identifier":s=CONFIG.PARAMETER_IDENTIFIER_WIDTH;n=getTd(e,t);i=b.trim(n.innerHTML);r+=getEditInputHtml(i,s,CONFIG.DEFAULT_MAX_LENGTH);break;case"param-validator":n=getTd(e,t);i=b.trim(n.innerHTML);r+=getEditInputHtml(i,s,CONFIG.DEFAULT_MAX_LENGTH);break;case"param-remark":s=CONFIG.PARAMETER_REMARK_WIDTH;n=getTd(e,t);i=b.trim(p.getParameter(e).remark);r+=getEditInputHtml(i,s,CONFIG.REMARK_MAX_LENGTH);break;default:throw Error("not implemented, key:"+t)}editing(e,i,t);n.innerHTML=r;processInputEvent(true);focusElement(b.g(ELEMENT_ID.EDIT_INPUT))};ws.validate=function(){showMessage(CONST.LOADING,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.PROCESSING);if(!processing())return;setTimeout(function(){ecFloater.show("validateFloater");e.get("validateFloater").setTitle("Validate Workspace");showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.PROCESSED);processed()},5e3)};ws.save=function(){if(!processing())return;ecFloater.show(ELEMENT_ID.SAVE_PANEL);e.get(ELEMENT_ID.SAVE_PANEL).setTitle("Save Workspace");processed()};ws.version=function(){if(!processing())return;e.get(ELEMENT_ID.VERSION_PANEL).setTitle("版本管理");ecFloater.show(ELEMENT_ID.VERSION_PANEL);setSelectedValue("radioCheckIn",-1);var t=b.g("div-version-panel");if(t){t.scrollTop=0}processed()};ws._processed=function(){processed()};ws.checkIn=function(){if(!confirm(MESSAGE.CONFIRM_CHECKIN))return;ecFloater.show(ELEMENT_ID.CHECKIN_PANEL);ecui.get(ELEMENT_ID.CHECKIN_PANEL).setTitle("Check In");var q="projectId="+p.getId()+"&projectData="+util.escaper.escapeInU(b.json.stringify(p.getData()))+"&projectDataOriginal="+util.escaper.escapeInU(b.json.stringify(_data.projectDataOriginal));showMessage(CONST.LOADING,ELEMENT_ID.CHECKIN_PANEL_MESSAGE,MESSAGE.PROCESSING);if(!processing())return;b.ajax.post(URL.checkIn,q,function(xhr,response){try{var obj=eval("("+response+")");p.init(obj.projectData);_data.projectDataOriginal=b.object.clone(obj.projectData);b.g(ELEMENT_ID.CHECKIN_PANEL_CONTENT).innerHTML=obj.log?obj.log:TEMPLATE.NO_DATA_CHECKED;bind(true);showMessage(CONST.LOAD,ELEMENT_ID.CHECKIN_PANEL_MESSAGE,MESSAGE.PROCESSED)}catch(e){showMessage(CONST.WARN,ELEMENT_ID.CHECKIN_PANEL_MESSAGE,MESSAGE.FATAL_ERROR)}finally{processed()}})};ws.closeSavePanel=function(){e.get(ELEMENT_ID.SAVE_PANEL).hide()};ws.closeVersionPanel=function(){e.get(ELEMENT_ID.VERSION_PANEL).hide()};ws.closeCheckOutPanel=function(){b.g(ELEMENT_ID.CHECKOUT_PANEL_MESSAGE).innerHTML="";b.g(ELEMENT_ID.CHECKOUT_PANEL_CONTENT).innerHTML="";ecui.get(ELEMENT_ID.CHECKOUT_PANEL).hide()};ws.closeCheckInPanel=function(){b.g(ELEMENT_ID.CHECKIN_PANEL_MESSAGE).innerHTML="";b.g(ELEMENT_ID.CHECKIN_PANEL_CONTENT).innerHTML="";ecui.get(ELEMENT_ID.CHECKIN_PANEL).hide()};ws.dataTypeSelectChanged=function(e,t){p.setParameter(e,t,"dataType");if(t=="object"||t=="array"){this.switchA(_curActionId)}};ws.radioVersionChanged=function(e){b.g("divVersion").innerHTML=p.getVersion()+" -> "+versionUpgrade(p.getVersion(),e)};ws.dataTypeKeyPressed=function(e,t){if(b.event.getKeyCode(e)==9){this.edit(t,"param-remark")}b.event.stop(e)};ws.finishEdit=function(t){if(!isEditing())return;var n=b.g(ELEMENT_ID.EDIT_INPUT);if(!n)return;var r=stopEditing(),i=b.trim(n.value),s=false,o;switch(r.key){case"mt":o=getDiv(r.id,r.key);p.setModuleName(r.id,i);updateCurMTree();break;case"param-name":case"param-identifier":case"param-validator":case"param-remark":o=getTd(r.id,r.key);var u=r.key;p.setParameter(r.id,i,u.substring(6,u.length));if(r.key==="param-remark"){i=remarkFilter(i)}break;default:throw Error("not implemented finish edit for key:"+r.key)}processInputEvent(false);var a=r.id;e.dom.setText(o,i);if(isEditing()){stopEditing()}return a};ws.doAddOrEditA=function(){if(!validate("formEditAFloater"))return;if(b.g("editAFloater-id").value==""){this.doAddA()}else{this.doEditA()}};ws.doAddOrEditP=function(){if(!validate("formEditPFloater"))return;if(b.g("editPFloater-id").value==""){this.doAddP()}else{this.doEditP()}};ws.doImportJSON=function(){if(!validate("formImportJSONFloater"))return;var e=b.g("importJSONFloater-text");var t=e.value;try{if(typeof JSON==="undefined"){alert("您用的啥浏览器啊?连JSON转换都不支持也~~~请考虑用新浏览器试试?谢谢啦,mua~~~!");return}var n=JSON.parse(t);e.value="";processJSONImport(n);this.switchA(_curActionId);this.cancelImportJSON()}catch(r){showMessage(CONST.WARN,ELEMENT_ID.IMPORT_JSON_MESSAGE,"JSON解析错误: "+r.message)}};ws.editA=function(t){if(!_isEditMode)return;var n=p.getAction(t);initEditAFloater();b.g("editAFloater-id").value=n.id;b.g("editAFloater-name").value=n.name;setSelectedValue("editAFloater-type",n.requestType);b.g("editAFloater-requestUrl").value=n.requestUrl;b.g("editAFloater-responseTemplate").value=n.responseTemplate;b.g("editAFloater-description").value=n.description;e.get("editAFloater").setTitle("模型管理 - 编辑请求");ecFloater.show("editAFloater")};ws.editP=function(t){if(!_isEditMode)return;var n=p.getPage(t);initEditPFloater();b.g("editPFloater-id").value=n.id;b.g("editPFloater-name").value=n.name;b.g("editPFloater-introduction").value=n.introduction;e.get("editAFloater").setTitle("模型管理 - 编辑页面");ecFloater.show("editPFloater")};ws.addA=function(t){initEditAFloater();b.g("editAFloater-pageId").value=t;e.get("editAFloater").setTitle("模型管理 - 添加新请求");ecFloater.show("editAFloater")};ws.addP=function(){initEditPFloater();e.get("editPFloater").setTitle("模型管理 - 添加新页面");ecFloater.show("editPFloater")};ws.doEditA=function(e){var t={};t.id=b.g("editAFloater-id").value-0;t.name=b.g("editAFloater-name").value;t.requestType=getSelectedValue("editAFloater-type");t.requestUrl=b.g("editAFloater-requestUrl").value;t.responseTemplate=b.g("editAFloater-responseTemplate").value;t.description=b.g("editAFloater-description").value;p.updateAction(t);updateCurMTree();ws.cancelEditA()};ws.doAddA=function(){var e={};e.pageId=b.g("editAFloater-pageId").value-0;e.name=b.g("editAFloater-name").value;e.requestType=getSelectedValue("editAFloater-type");e.requestUrl=b.g("editAFloater-requestUrl").value;e.responseTemplate=b.g("editAFloater-responseTemplate").value;e.description=b.g("editAFloater-description").value;var t=p.addAction(e);updateCurMTree();ws.cancelEditA();this.switchA(t)};ws.doAddP=function(){var e={};e.moduleId=_curModuleId;e.name=b.g("editPFloater-name").value;e.introduction=b.g("editPFloater-introduction").value;p.addPage(e);updateCurMTree();ws.cancelEditP()};ws.doEditP=function(e){var t={};t.id=b.g("editPFloater-id").value-0;t.name=b.g("editPFloater-name").value;t.introduction=b.g("editPFloater-introduction").value;p.updatePage(t);updateCurMTree();ws.cancelEditP()};ws.cancelEditA=function(){ecui.get("editAFloater").hide()};ws.cancelEditP=function(){ecui.get("editPFloater").hide()};ws.cancelImportJSON=function(){ecui.get("importJSONFloater").hide()};ws.importJSON=function(){ecFloater.show("importJSONFloater")};ws.cancelSaveVSS=function(){ecui.get("saveVSSFloater").hide()};ws.switchToEditMode=function(){var q="id="+p.getId();showMessage(CONST.LOADING,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.CHECK_LOCK_CONFLICKTION);if(!processing(ELEMENT_ID.WORKSPACE_MESSAGE))return;b.ajax.post(URL.lock,q,function(xhr,response){try{var obj=eval("("+response+")");if(obj.isOk){storeViewState();p.init(obj.projectData);_data.projectDataOriginal=b.object.clone(obj.projectData);setButtonsViewState(CONST.EDIT);_isEditMode=true;initModules();renderModuleTreeList();recoverViewState();showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.CHECK_LOCK_CONFLICKTION_COMPLETED)}else{showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,obj.errMsg)}}catch(e){showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.FATAL_ERROR)}finally{processed()}})};ws.switchToViewMode=function(e){storeViewState();if(e){initSaveVSSFloater()}else{if(!confirm(MESSAGE.CONFIRM_CANCEL))return;var t="id="+p.getId();b.ajax.post(URL.unlock,t,function(e,t){});p.init(b.object.clone(_data.projectDataOriginal));switchToViewModeSub()}};ws.quickSave=function(){var q="id="+p.getId()+"&projectData="+util.escaper.escapeInU(getProjectDataJson())+"&deletedObjectListData="+util.escaper.escapeInU(b.json.stringify(_deletedObjectList))+"&versionPosition=4&description=quick save";showMessage(CONST.LOADING,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.SAVING);if(!processing(ELEMENT_ID.WORKSPACE_MESSAGE))return;b.ajax.post(URL.checkIn,q,function(xhr,response){try{var obj=eval("("+response+")");if(obj.isOk){p.init(obj.projectData);_data.projectDataOriginal=b.object.clone(obj.projectData);_data.checkList=obj.checkList;initVersionPanel();switchToViewModeSub();ws.cancelSaveVSS();showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.SAVED)}else{showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,obj.errMsg)}}catch(e){showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.FATAL_ERROR)}finally{processed()}});};ws.doSaveVSS=function(){if(!validate("formSaveVSSFloater"))return;var q="id="+p.getId()+"&projectData="+util.escaper.escapeInU(getProjectDataJson())+"&deletedObjectListData="+util.escaper.escapeInU(b.json.stringify(_deletedObjectList))+"&versionPosition="+getSelectedValue("radioVersion")+"&description="+b.g("txtDescription").value;showMessage(CONST.LOADING,ELEMENT_ID.VSS_PANEL_MESSAGE,MESSAGE.SAVING);if(!processing(ELEMENT_ID.VSS_PANEL_MESSAGE))return;b.ajax.post(URL.checkIn,q,function(xhr,response){try{var obj=eval("("+response+")");if(obj.isOk){p.init(obj.projectData);_data.projectDataOriginal=b.object.clone(obj.projectData);_data.checkList=obj.checkList;initVersionPanel();switchToViewModeSub();ws.cancelSaveVSS();showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.SAVED)}else{showMessage(CONST.WARN,ELEMENT_ID.VSS_PANEL_MESSAGE,obj.errMsg)}}catch(e){showMessage(CONST.WARN,ELEMENT_ID.VSS_PANEL_MESSAGE,MESSAGE.FATAL_ERROR)}finally{processed()}})};ws.showOpColumn=function(e,t){if(!_isEditMode)return;b.show("div-param-op-"+t);b.event.stop(e)};ws.hideOpColumn=function(e,t){if(!_isEditMode)return;b.hide("div-param-op-"+t);b.event.stop(e)};ws.readProjectOfVersion=function(){var versionId=getSelectedValue("radioCheckIn");if(!versionId){showMessage(CONST.WARN,ELEMENT_ID.VERSION_PANEL_MESSAGE,MESSAGE.CHOOSE_AT_FIRST);return}var q="versionId="+versionId;showMessage(CONST.LOADING,ELEMENT_ID.VERSION_PANEL_MESSAGE,MESSAGE.VERSION_LOADING);if(!processing(ELEMENT_ID.VERSION_PANEL_MESSAGE))return;b.ajax.post(URL.queryVersion,q,function(xhr,response){try{var obj=eval("("+response+")");p.init(obj.projectData);setButtonsViewState(CONST.VERSION);_isEditMode=false;initModules();ws.closeVersionPanel();showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.VERSION_LOAD)}catch(e){showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.FATAL_ERROR)}finally{processed()}})};ws.exitVersion=function(){p.init(_data.projectDataOriginal);setButtonsViewState(CONST.NORMAL);_isEditMode=false;initModules();showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.VERSION_EXIT)};ws.switchVersion=function(){if(!confirm("确定要恢复到另一版本吗?"))return;var versionId=getSelectedValue("radioCheckIn");if(!versionId){showMessage(CONST.WARN,ELEMENT_ID.VERSION_PANEL_MESSAGE,MESSAGE.CHOOSE_AT_FIRST);return}var q="versionId="+versionId;showMessage(CONST.LOADING,ELEMENT_ID.VERSION_PANEL_MESSAGE,MESSAGE.VERSION_SWITCHING);if(!processing(ELEMENT_ID.VERSION_PANEL_MESSAGE))return;b.ajax.post(URL.switchVersion,q,function(xhr,response){try{var obj=eval("("+response+")");if(obj.isOk){p.init(obj.projectData);showMessage(CONST.LOAD,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.VERSION_SWITCHED)}else{throw Error()}}catch(e){showMessage(CONST.WARN,ELEMENT_ID.WORKSPACE_MESSAGE,MESSAGE.VERSION_SWITCH_ERROR);p.init(_data.projectDataOriginal)}finally{setButtonsViewState(CONST.NORMAL);_isEditMode=false;initModules();ws.closeVersionPanel();processed()}})};ws.paramShrink=function(e){hideAllChildParameters(p.getParameter(e));var t=b.g("div-param-expander-"+e);if(t){t.onclick=function(){ws.paramExpand(e);return false};b.dom.removeClass(t,"more");b.dom.addClass(t,"more-fold")}};ws.paramExpand=function(e){showAllChildParameters(p.getParameter(e));var t=b.g("div-param-expander-"+e);if(t){t.onclick=function(){ws.paramShrink(e);return false};b.dom.removeClass(t,"more-fold");b.dom.addClass(t,"more")}};ws.toggleMockDisplay=function(){b.g("btnToggleMockDisplay").value=(_isMockDisplay?"显示":"隐藏")+"Mock标签";_isMockDisplay=!_isMockDisplay;ws.switchA(_curActionId,true)};})() \ No newline at end of file diff --git a/WebContent/stat/js/core/tangram-fix.js b/WebContent/stat/js/core/tangram-fix.js index 59b43a191..1e2ec2d12 100644 --- a/WebContent/stat/js/core/tangram-fix.js +++ b/WebContent/stat/js/core/tangram-fix.js @@ -5,14 +5,14 @@ var baidu_ajax_get = baidu.ajax.get; baidu.ajax.get = function(url, func) { var seed = new Date().getTime(); - url += (url.indexOf("?") == -1 ? "?b" : "&b") + seed + "=1"; + url += (url.indexOf("?") == -1 ? "?seed" : "&seed") + "=" + seed; baidu_ajax_get(url, func); }; var baidu_ajax_post = baidu.ajax.post; baidu.ajax.post = function(url, q, func) { var seed = new Date().getTime(); - q = ((q == null || baidu.trim(q).length == 0) ? "" : (q + "&")) + "b" + seed + "=1"; + q = ((q == null || baidu.trim(q).length == 0) ? "" : (q + "&")) + "seed" + "=" + seed; baidu_ajax_post(url, q, func); }; diff --git a/WebContent/stat/js/routes.js b/WebContent/stat/js/routes.js index 4fbd6e85f..9a288a6b0 100644 --- a/WebContent/stat/js/routes.js +++ b/WebContent/stat/js/routes.js @@ -4,7 +4,8 @@ home: { 'projects': '/org/projects.action', 'productlines': '/org/home/productlines.action', - 'groups': '/org/home/groups.action' + 'groups': '/org/home/groups.action', + 'grouplist': '/org/group/groups.action' }, group: { 'all': '/org/group/all.action', @@ -30,6 +31,12 @@ }, workspace: { 'mine': '/workspace/myWorkspace.action' + }, + notify: { + 'unread': '/account/getUnreadNotificationList.action', + 'clear': '/account/clearUnreadNotifications.action', + 'all': '/account/getNotificationList.action', + 'delete': '/account/readAllNotification.action' } }; @@ -113,9 +120,18 @@ if (picked.indexOf(user.account) != -1) { return; } - if (user.account.indexOf(val) != -1) { - remained.push(user); - } + + if (user.account && user.account.indexOf(val) != -1) { + remained.push(user); + } else if (user.name && user.name.indexOf(val) != -1) { + remained.push(user); + } else if (user.realName && user.realName.indexOf(val) != -1) { + remained.push(user); + } else if (user.realNamePinyin && user.realNamePinyin.indexOf(val) != -1) { + remained.push(user); + } else if (user.namePinyin && user.namePinyin.indexOf(val) != -1) { + remained.push(user); + } }); if (remained.length == 0) { remained.push({block:true}) @@ -152,4 +168,212 @@ }); } } -})($); \ No newline at end of file +})($); + + +$(function() { + var con = $('.messages-container'); + if (con.length == 0) { + return; + } + + var btns = '\ + \ + '; + var tmpl = '
    \ + {{#changelogs}}
  • {{{desc}}}
  • {{/changelogs}}\ +
'; + var noMsgs = '
没有消息提醒
'; + + var label = $('.messages-trigger .label'); + + var test = { + changelogs : [ { + id : 1, + type : 'project', + operate : 'modify', + id : '123', + field : '名称', + from : '项目A', + to : '项目B', + operatorId : 21, + operator : '思竹', + date : '2014-3-21', + detail : 11 + }, { + id : 1, + type : 'project', + operate : 'delete', + id : '123', + field : '', + from : '测试项目', + to : '', + operatorId : 21, + operator : '思竹', + date : '2014-3-21', + detail : 11 + }, { + id : 2, + type : 'action', + operate : 'modify', + id : '1223', + field : '名称', + from : '请求A', + to : '请求A+', + operatorId : 21, + operator : '思竹', + date : '2014-3-21', + detail : 22 + }, { + id : 3, + type : 'action', + operate : 'delete', + id : '1223', + field : '', + from : '请求A', + to : '', + operatorId : 21, + operator : '思竹', + date : '2014-3-21', + detail : 33 + }] + } + + $.get($.route('notify.unread'), {}, function(data) { + if (data.length == 0) { + reset(); + } else { + generateHTML(data); + } + }, 'JSON'); + + function href(text, link) { + return '' + text + ''; + } + function create() { + return ' '; + } + function del() { + return ' '; + } + function update() { + return ' '; + } + + function wrap(name) { + return '"' + name + '"'; + } + + var notifyTmpl = '{{text}} {{targetUser.name}} {{operate}}了项目 {{param2}} ({{createTimeStr}})'; + function renderNotification(obj) { + if (obj.typeId == 1) { + obj.style = 'info'; + obj.text = '改'; + obj.operate = '修改' + } else if (obj.typeId == 2) { + obj.style = 'success'; + obj.text = '增'; + obj.operate = '把你加入' + } + return $.render(notifyTmpl, obj); + } + function generateHTML(data) { +// var chMapper = { +// project: '项目', +// action: '接口' +// } + var translated = []; + data.forEach(function(log) { + translated.push({ + desc: renderNotification(log), + id: log.id + }); +// console.log(log); +// var type = log.type, operate = log.operate; +// var cnName = chMapper[type] || '实体'; +// if (operate == 'create') { +// log.desc = create() + href(log.operator, log.operatorId) + ' 创建了' + cnName + ' ' + wrap(log.to) + ''; +// } else if (operate == 'delete') { +// log.desc = del() + href(log.operator, log.operatorId) + ' 删除了' + cnName + ' ' + wrap(log.from) + ''; +// } else if (operate == 'modify') { +// log.desc = update() + href(log.operator, log.operatorId) + ' 将' + cnName + ' ' + wrap(log.from) + ' 的名称修改为 ' + wrap(log.to) + ''; +// } + }); + con.find('.msgs').html($.render(tmpl, { + changelogs: translated + })) + + fillBtns(); + + label.text(data.length).show(); + } + + var btnsInited = false; + + function fillBtns() { + if (btnsInited) { + return; + } + btnsInited = true; + con.find('.btns').html(btns); + con.find('.close-btn').click(function() { + $(this).parents('li').toggleClass('open'); + }) + con.find('.set-btn').click(function() { + window.location.href = '/account/mySetting.action'; + }) + + con.delegate('button.close', 'click', function(e) { + $(this).parent().remove(); + label.text(label.text() - 1); + if (label.text() == '0') { + reset(); + } + }); + + con.find('.clear-btn').click(function() { + var noMsgsEle = $('.messages-container .no-msgs'); + if (noMsgsEle.length == 1) { + if (noMsgsEle.hasClass('shake')) { + return; + } + noMsgsEle.addClass('shake'); + setTimeout(function() { + noMsgsEle.removeClass('shake'); + }, 1000); + return; + } + $.confirm({ + content: '确定要清空所有的提醒消息么?', + title: '清空提醒消息', + confirmText: '确定', + cancelCallback: function() { + }, + confirmClicked: function() { + var modal = $(this); + $.post($.route('notify.delete'), {}, function(data) { + if (data.code != 200) { + alert(data.msg) + } else { + reset(); + } + modal.modal('hide'); + }, "JSON") + } + }) + }) + + } + + function reset() { + fillBtns(); + con.find('.msgs').html(noMsgs); + con.parents('li').removeClass('open'); + label.hide(); + } + + $('.messages-trigger').click(function(e) { + e.preventDefault(); + $(this).parents('li').toggleClass('open'); + }) +}) \ No newline at end of file diff --git a/WebContent/stat/js/ui/floater/css/floater.css b/WebContent/stat/js/ui/floater/css/floater.css index 46662300f..fe868f807 100644 --- a/WebContent/stat/js/ui/floater/css/floater.css +++ b/WebContent/stat/js/ui/floater/css/floater.css @@ -1,9 +1,93 @@ -.floaterd {padding-top:3px;} -.floaterd-top {background: #3B5C55} -.floaterd-bottom {display:none} -.floater {position:absolute !important;} -.floater-title {border-right:1px solid #CBE9B7;border-left:1px solid #CBE9B7;border-top:1px solid #CBE9B7;cursor:move;position:absolute;left:0;top:0;height:23px;padding:4px 10px 0 18px;background:url(img/global_bg.png) 0 -150px repeat-x;font-size:12px;color:#E2FEC4;font-weight:bold;} -.floater-close {position:absolute;right:5px;top:5px;font-size:1px;border:0px;float:right;display:block;width:19px;height:19px;background:url(img/btn.gif) -83px -49px;cursor:pointer;} -.floater-content {padding:37px 18px 9px;border-right:1px solid #CBE9B7;border-left:1px solid #CBE9B7;border-bottom:1px solid #CBE9B7;background:#F3FBEC} -.floater-inner {overflow-y:auto;overflow-x:hidden} -.floater-corner {background: #fff} +.floaterd { + padding-top: 3px; +} + +.floaterd-top { + background: #3B5C55 +} + +.floaterd-bottom { + display: none +} + +.floater { + position: absolute !important; + border-radius: 6px; + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .2); + outline: none; + border: none; +} + +.ec-form.floater { + padding-top: 52px; +} + +.floater-title { + cursor: move; + border-radius: 6px 6px 0 0; + position: absolute; + left: 0; + top: 0; + height: 52px; + padding: 4px 10px 0 18px; + font-size: 18px; + color: #333; + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; + font-weight: bold; + position: absolute +} + +.floater-close { + position: absolute; + right: 18px; + top: 14px; + font-size: 1px; + font-size: 22px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .2; + cursor: pointer; +} + +.floater-close:after { + content: '×'; +} + +.floater-close:hover { + opacity: .4; +} + +.floater-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + background-color: #fff; + background-clip: padding-box; + border-radius: 0 0 6px 6px; + outline: none; +} + +.floater-inner { + overflow-y: auto; + overflow-x: hidden +} + +.floater-corner { + background: #fff +} + +.div-floater-control { + padding: 15px 20px 2px; + margin-top: 20px; + text-align: right; + border-top: 1px solid #e5e5e5; + margin-left: -19px; + margin-right: -19px; +} \ No newline at end of file diff --git a/WebContent/stat/js/util/console-compability.js b/WebContent/stat/js/util/console-compability.js new file mode 100644 index 000000000..645349990 --- /dev/null +++ b/WebContent/stat/js/util/console-compability.js @@ -0,0 +1,23 @@ +!function() { + // console handler + if (typeof window.console === 'undefined') { + window.console = {}; + } + + var mockConsoleKeys = ['log', 'info', 'error', 'dir']; + + var k = ''; + for (var i = 0; i < mockConsoleKeys.length; i++) { + k = mockConsoleKeys[i]; + if (typeof console[k] === 'undefined') { + console[k] = genereateConsoleMethod(k); + } + } + + function genereateConsoleMethod(key) { + return function(msg) { + if (window.showConsoleMsg) + document.body.innerHTML += '
[' + key + ']:' + msg; + }; + } +}(); \ No newline at end of file diff --git a/WebContent/stat/js/util/dateFormat.min.js b/WebContent/stat/js/util/dateFormat.min.js new file mode 100644 index 000000000..dbd575950 --- /dev/null +++ b/WebContent/stat/js/util/dateFormat.min.js @@ -0,0 +1,2 @@ +/*! jquery-dateFormat 10-05-2014 */ +var DateFormat={};!function(a){var b=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],c=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],d=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],e=["January","February","March","April","May","June","July","August","September","October","November","December"],f={Jan:"01",Feb:"02",Mar:"03",Apr:"04",May:"05",Jun:"06",Jul:"07",Aug:"08",Sep:"09",Oct:"10",Nov:"11",Dec:"12"},g=/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.?\d{0,3}[Z\-+]?(\d{2}:?\d{2})?/;a.format=function(){function a(a){return b[parseInt(a,10)]||a}function h(a){return c[parseInt(a,10)]||a}function i(a){var b=parseInt(a,10)-1;return d[b]||a}function j(a){var b=parseInt(a,10)-1;return e[b]||a}function k(a){return f[a]||a}function l(a){var b,c,d,e,f,g=a,h="";return-1!==g.indexOf(".")&&(e=g.split("."),g=e[0],h=e[1]),f=g.split(":"),3===f.length?(b=f[0],c=f[1],d=f[2].replace(/\s.+/,"").replace(/[a-z]/gi,""),g=g.replace(/\s.+/,"").replace(/[a-z]/gi,""),{time:g,hour:b,minute:c,second:d,millis:h}):{time:"",hour:"",minute:"",second:"",millis:""}}function m(a,b){for(var c=b-String(a).length,d=0;c>d;d++)a="0"+a;return a}return{parseDate:function(a){var b={date:null,year:null,month:null,dayOfMonth:null,dayOfWeek:null,time:null};if("number"==typeof a)return this.parseDate(new Date(a));if("function"==typeof a.getFullYear)b.year=String(a.getFullYear()),b.month=String(a.getMonth()+1),b.dayOfMonth=String(a.getDate()),b.time=l(a.toTimeString());else if(-1!=a.search(g))values=a.split(/[T\+-]/),b.year=values[0],b.month=values[1],b.dayOfMonth=values[2],b.time=l(values[3].split(".")[0]);else switch(values=a.split(" "),6===values.length&&isNaN(values[5])&&(values[values.length]="()"),values.length){case 6:b.year=values[5],b.month=k(values[1]),b.dayOfMonth=values[2],b.time=l(values[3]);break;case 2:subValues=values[0].split("-"),b.year=subValues[0],b.month=subValues[1],b.dayOfMonth=subValues[2],b.time=l(values[1]);break;case 7:case 9:case 10:b.year=values[3],b.month=k(values[1]),b.dayOfMonth=values[2],b.time=l(values[4]);break;case 1:subValues=values[0].split(""),b.year=subValues[0]+subValues[1]+subValues[2]+subValues[3],b.month=subValues[5]+subValues[6],b.dayOfMonth=subValues[8]+subValues[9],b.time=l(subValues[13]+subValues[14]+subValues[15]+subValues[16]+subValues[17]+subValues[18]+subValues[19]+subValues[20]);break;default:return null}return b.date=new Date(b.year,b.month-1,b.dayOfMonth),b.dayOfWeek=String(b.date.getDay()),b},date:function(b,c){try{var d=this.parseDate(b);if(null===d)return b;for(var e=(d.date,d.year),f=d.month,g=d.dayOfMonth,k=d.dayOfWeek,l=d.time,n="",o="",p="",q=!1,r=0;r=12?"PM":"AM",n="";break;case"p":o+=l.hour>=12?"p.m.":"a.m.",n="";break;case"E":o+=h(k),n="";break;case"'":n="",q=!0;break;default:o+=s,n=""}}return o+=p}catch(u){return console&&console.log&&console.log(u),b}},prettyDate:function(a){var b,c,d;return("string"==typeof a||"number"==typeof a)&&(b=new Date(a)),"object"==typeof a&&(b=new Date(a.toString())),c=((new Date).getTime()-b.getTime())/1e3,d=Math.floor(c/86400),isNaN(d)||0>d?void 0:60>c?"just now":120>c?"1 minute ago":3600>c?Math.floor(c/60)+" minutes ago":7200>c?"1 hour ago":86400>c?Math.floor(c/3600)+" hours ago":1===d?"Yesterday":7>d?d+" days ago":31>d?Math.ceil(d/7)+" weeks ago":d>=31?"more than 5 weeks ago":void 0},toBrowserTimeZone:function(a,b){return this.date(new Date(a),b||"MM/dd/yyyy HH:mm:ss")}}}()}(DateFormat),function(a){a.format=DateFormat.format}(jQuery); \ No newline at end of file diff --git a/WebContent/stat/js/util/jquery-rapped.js b/WebContent/stat/js/util/jquery-rapped.js new file mode 100644 index 000000000..3055313bb --- /dev/null +++ b/WebContent/stat/js/util/jquery-rapped.js @@ -0,0 +1,12 @@ +define('jquery', [], function(require) { + + /*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/
","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); + + // wrap for RAP + if (window.wrapJQueryForRAP) { + window.wrapJQueryForRAP($); + } + $.providedByRAP = true; + return $.noConflict(true); +}); \ No newline at end of file diff --git a/WebContent/stat/js/util/mock-min.js b/WebContent/stat/js/util/mock-min.js index 2e3b80d42..1c757730f 100644 --- a/WebContent/stat/js/util/mock-min.js +++ b/WebContent/stat/js/util/mock-min.js @@ -1,3 +1,1624 @@ -/*! mockjs 18-04-2014 */ -(function(a){var b={version:"0.1.1",_mocked:{}},c=function(){var b={};return b.extend=function(){var c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length;for(1===j&&(h=this,i=0);j>i;i++)if(c=arguments[i])for(d in c)e=h[d],f=c[d],h!==f&&f!==a&&(b.isArray(f)||b.isObject(f)?(b.isArray(f)&&(g=e&&b.isArray(e)?e:[]),b.isObject(f)&&(g=e&&b.isObject(e)?e:{}),h[d]=b.extend(g,f)):h[d]=f);return h},b.each=function(a,b,c){var d,e;if("number"===this.type(a))for(d=0;a>d;d++)b(d,d);else if(a.length===+a.length)for(d=0;d1/(b+c)*b?!d:d):Math.random()>=.5},bool:function(a,b,c){return this.boolean(a,b,c)},natural:function(a,b){return a="undefined"!=typeof a?parseInt(a,10):0,b="undefined"!=typeof b?parseInt(b,10):9007199254740992,Math.round(Math.random()*(b-a))+a},integer:function(a,b){return a="undefined"!=typeof a?parseInt(a,10):-9007199254740992,b="undefined"!=typeof b?parseInt(b,10):9007199254740992,Math.round(Math.random()*(b-a))+a},"int":function(a,b){return this.integer(a,b)},"float":function(b,c,d,e){d=d===a?0:d,d=Math.max(Math.min(d,17),0),e=e===a?17:e,e=Math.max(Math.min(e,17),0);for(var f=this.integer(b,c)+".",g=0,h=this.natural(d,e);h>g;g++)f+=this.character("number");return parseFloat(f,10)},character:function(a){var c={lower:"abcdefghijklmnopqrstuvwxyz",upper:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",number:"0123456789",symbol:"!@#$%^&*()[]"};return c.alpha=c.lower+c.upper,c.undefined=c.lower+c.upper+c.number+c.symbol,a=c[(""+a).toLowerCase()]||a,a.charAt(b.natural(0,a.length-1))},"char":function(a){return this.character(a)},string:function(c,d,e){var f;3===arguments.length&&(f=b.natural(d,e)),2===arguments.length&&("string"==typeof arguments[0]?f=d:(f=b.natural(c,d),c=a)),1===arguments.length&&(f=c,c=a),0===arguments.length&&(f=b.natural(3,7));for(var g="",h=0;f>h;h++)g+=b.character(c);return g},str:function(a,b,c){return this.string(a,b,c)},range:function(a,b,c){arguments.length<=1&&(b=a||0,a=0),c=arguments[2]||1;for(var d=Math.max(Math.ceil((b-a)/c),0),e=0,f=new Array(d);d>e;)f[e++]=a,a+=c;return f}}),b.extend({patternLetters:{yyyy:"getFullYear",yy:function(a){return(""+a.getFullYear()).slice(2)},y:"yy",MM:function(a){var b=a.getMonth()+1;return 10>b?"0"+b:b},M:function(a){return a.getMonth()+1},dd:function(a){var b=a.getDate();return 10>b?"0"+b:b},d:"getDate",HH:function(a){var b=a.getHours();return 10>b?"0"+b:b},H:"getHours",hh:function(a){var b=a.getHours()%12;return 10>b?"0"+b:b},h:function(a){return a.getHours()%12},mm:function(a){var b=a.getMinutes();return 10>b?"0"+b:b},m:"getMinutes",ss:function(a){var b=a.getSeconds();return 10>b?"0"+b:b},s:"getSeconds",SS:function(a){var b=a.getMilliseconds();return 10>b&&"00"+b||100>b&&"0"+b||b},S:"getMilliseconds",A:function(a){return a.getHours()<12?"AM":"PM"},a:function(a){return a.getHours()<12?"am":"pm"}}}),b.extend({rformat:new RegExp(function(){var a=[];for(var c in b.patternLetters)a.push(c);return"("+a.join("|")+")"}(),"g"),format:function(a,c){var d=b.patternLetters,e=b.rformat;return c.replace(e,function(b,c){return"function"==typeof d[c]?d[c](a):d[c]in d?arguments.callee(b,d[c]):a[d[c]]()})},randomDate:function(b,c){return b=b===a?new Date(0):b,c=c===a?new Date:c,new Date(Math.random()*(c.getTime()-b.getTime()))},date:function(a){return a=a||"yyyy-MM-dd",this.format(this.randomDate(),a)},time:function(a){return a=a||"HH:mm:ss",this.format(this.randomDate(),a)},datetime:function(a){return a=a||"yyyy-MM-dd HH:mm:ss",this.format(this.randomDate(),a)}}),b.extend({ad_size:["300x250","250x250","240x400","336x280","180x150","720x300","468x60","234x60","88x31","120x90","120x60","120x240","125x125","728x90","160x600","120x600","300x600"],screen_size:["320x200","320x240","640x480","800x480","800x480","1024x600","1024x768","1280x800","1440x900","1920x1200","2560x1600"],video_size:["720x480","768x576","1280x720","1920x1080"],image:function(b,c,d,e,f){return 4===arguments.length&&(f=e,e=a),3===arguments.length&&(f=d,d=a),b||(b=this.pick(this.ad_size)),c&&~c.indexOf("#")&&(c=c.slice(1)),d&&~d.indexOf("#")&&(d=d.slice(1)),"http://dummyimage.com/"+b+(c?"/"+c:"")+(d?"/"+d:"")+(e?"."+e:"")+(f?"&text="+f:"")},img:function(){return this.image.apply(this,arguments)}}),b.extend({brandColors:{"4ormat":"#fb0a2a","500px":"#02adea","About.me (blue)":"#00405d","About.me (yellow)":"#ffcc33",Addvocate:"#ff6138",Adobe:"#ff0000",Aim:"#fcd20b",Amazon:"#e47911",Android:"#a4c639","Angie's List":"#7fbb00",AOL:"#0060a3",Atlassian:"#003366",Behance:"#053eff","Big Cartel":"#97b538",bitly:"#ee6123",Blogger:"#fc4f08",Boeing:"#0039a6","Booking.com":"#003580",Carbonmade:"#613854",Cheddar:"#ff7243","Code School":"#3d4944",Delicious:"#205cc0",Dell:"#3287c1",Designmoo:"#e54a4f",Deviantart:"#4e6252","Designer News":"#2d72da",Devour:"#fd0001",DEWALT:"#febd17","Disqus (blue)":"#59a3fc","Disqus (orange)":"#db7132",Dribbble:"#ea4c89",Dropbox:"#3d9ae8",Drupal:"#0c76ab",Dunked:"#2a323a",eBay:"#89c507",Ember:"#f05e1b",Engadget:"#00bdf6",Envato:"#528036",Etsy:"#eb6d20",Evernote:"#5ba525","Fab.com":"#dd0017",Facebook:"#3b5998",Firefox:"#e66000","Flickr (blue)":"#0063dc","Flickr (pink)":"#ff0084",Forrst:"#5b9a68",Foursquare:"#25a0ca",Garmin:"#007cc3",GetGlue:"#2d75a2",Gimmebar:"#f70078",GitHub:"#171515","Google Blue":"#0140ca","Google Green":"#16a61e","Google Red":"#dd1812","Google Yellow":"#fcca03","Google+":"#dd4b39",Grooveshark:"#f77f00",Groupon:"#82b548","Hacker News":"#ff6600",HelloWallet:"#0085ca","Heroku (light)":"#c7c5e6","Heroku (dark)":"#6567a5",HootSuite:"#003366",Houzz:"#73ba37",HTML5:"#ec6231",IKEA:"#ffcc33",IMDb:"#f3ce13",Instagram:"#3f729b",Intel:"#0071c5",Intuit:"#365ebf",Kickstarter:"#76cc1e",kippt:"#e03500",Kodery:"#00af81",LastFM:"#c3000d",LinkedIn:"#0e76a8",Livestream:"#cf0005",Lumo:"#576396",Mixpanel:"#a086d3",Meetup:"#e51937",Nokia:"#183693",NVIDIA:"#76b900",Opera:"#cc0f16",Path:"#e41f11","PayPal (dark)":"#1e477a","PayPal (light)":"#3b7bbf",Pinboard:"#0000e6",Pinterest:"#c8232c",PlayStation:"#665cbe",Pocket:"#ee4056",Prezi:"#318bff",Pusha:"#0f71b4",Quora:"#a82400","QUOTE.fm":"#66ceff",Rdio:"#008fd5",Readability:"#9c0000","Red Hat":"#cc0000",Resource:"#7eb400",Rockpack:"#0ba6ab",Roon:"#62b0d9",RSS:"#ee802f",Salesforce:"#1798c1",Samsung:"#0c4da2",Shopify:"#96bf48",Skype:"#00aff0",Snagajob:"#f47a20",Softonic:"#008ace",SoundCloud:"#ff7700","Space Box":"#f86960",Spotify:"#81b71a",Sprint:"#fee100",Squarespace:"#121212",StackOverflow:"#ef8236",Staples:"#cc0000","Status Chart":"#d7584f",Stripe:"#008cdd",StudyBlue:"#00afe1",StumbleUpon:"#f74425","T-Mobile":"#ea0a8e",Technorati:"#40a800","The Next Web":"#ef4423",Treehouse:"#5cb868",Trulia:"#5eab1f",Tumblr:"#34526f","Twitch.tv":"#6441a5",Twitter:"#00acee",TYPO3:"#ff8700",Ubuntu:"#dd4814",Ustream:"#3388ff",Verizon:"#ef1d1d",Vimeo:"#86c9ef",Vine:"#00a478",Virb:"#06afd8","Virgin Media":"#cc0000",Wooga:"#5b009c","WordPress (blue)":"#21759b","WordPress (orange)":"#d54e21","WordPress (grey)":"#464646",Wunderlist:"#2b88d9",XBOX:"#9bc848",XING:"#126567","Yahoo!":"#720e9e",Yandex:"#ffcc00",Yelp:"#c41200",YouTube:"#c4302b",Zalongo:"#5498dc",Zendesk:"#78a300",Zerply:"#9dcc7a",Zootool:"#5e8b1d"},brands:function(){var a=[];for(var b in this.brandColors)a.push(b);return a},dataImageHolder:function(a){return"holder.js/"+a},dataImage:function(b,c){var d="undefined"!=typeof document&&document.createElement("canvas"),e=d&&d.getContext&&d.getContext("2d");if(!d||!e)return"";b||(b=this.pick(this.ad_size)),c=c!==a?c:b,b=b.split("x");var f=parseInt(b[0],10),g=parseInt(b[1],10),h=this.brandColors[this.pick(this.brands())],i="#FFF",j=14,k="sans-serif";return d.width=f,d.height=g,e.textAlign="center",e.textBaseline="middle",e.fillStyle=h,e.fillRect(0,0,f,g),e.fillStyle=i,e.font="bold "+j+"px "+k,e.fillText(c,f/2,g/2,f),d.toDataURL("image/png")}}),b.extend({color:function(){var a=Math.floor(16777215*Math.random()).toString(16);return a="#"+("000000"+a).slice(-6)}}),b.extend({capitalize:function(a){return a.charAt(0).toUpperCase()+a.substr(1)},upper:function(a){return a.toUpperCase()},lower:function(a){return a.toLowerCase()},pick:function(a){return a[this.natural(0,a.length-1)]},shuffle:function(a){for(var b=a.slice(0),c=[],d=0,e=b.length,f=0;e>f;f++)d=this.natural(0,b.length-1),c.push(b[d]),b.splice(d,1);return c}}),b.extend({paragraph:function(a,c){var d;0===arguments.length&&(d=b.natural(3,7)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var e=[],f=0;d>f;f++)e.push(b.sentence());return e.join(" ")},sentence:function(a,c){var d;0===arguments.length&&(d=b.natural(12,18)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var e=[],f=0;d>f;f++)e.push(b.word());return b.capitalize(e.join(" "))+"."},word:function(a,c){var d;0===arguments.length&&(d=b.natural(3,10)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var e="",f=0;d>f;f++)e+=b.character("lower");return e},title:function(a,c){var d,e=[];0===arguments.length&&(d=b.natural(3,7)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var f=0;d>f;f++)e.push(this.capitalize(this.word()));return e.join(" ")}}),b.extend({first:function(){var a=["James","John","Robert","Michael","William","David","Richard","Charles","Joseph","Thomas","Christopher","Daniel","Paul","Mark","Donald","George","Kenneth","Steven","Edward","Brian","Ronald","Anthony","Kevin","Jason","Matthew","Gary","Timothy","Jose","Larry","Jeffrey","Frank","Scott","Eric"].concat(["Mary","Patricia","Linda","Barbara","Elizabeth","Jennifer","Maria","Susan","Margaret","Dorothy","Lisa","Nancy","Karen","Betty","Helen","Sandra","Donna","Carol","Ruth","Sharon","Michelle","Laura","Sarah","Kimberly","Deborah","Jessica","Shirley","Cynthia","Angela","Melissa","Brenda","Amy","Anna"]);return this.pick(a)},last:function(){var a=["Smith","Johnson","Williams","Brown","Jones","Miller","Davis","Garcia","Rodriguez","Wilson","Martinez","Anderson","Taylor","Thomas","Hernandez","Moore","Martin","Jackson","Thompson","White","Lopez","Lee","Gonzalez","Harris","Clark","Lewis","Robinson","Walker","Perez","Hall","Young","Allen"];return this.pick(a)},name:function(a){return this.first()+" "+(a?this.first()+" ":"")+this.last()}}),b.extend({url:function(){return"http://"+this.domain()+"/"+this.word()},domain:function(a){return this.word()+"."+(a||this.tld())},email:function(a){return this.character("lower")+"."+this.last().toLowerCase()+"@"+this.last().toLowerCase()+"."+this.tld()},ip:function(){return this.natural(0,255)+"."+this.natural(0,255)+"."+this.natural(0,255)+"."+this.natural(0,255)},tlds:["com","org","edu","gov","co.uk","net","io"],tld:function(){return this.pick(this.tlds)}}),b.extend({areas:["东北","华北","华东","华中","华南","西南","西北"],area:function(){return this.pick(this.areas)},regions:["110000 北京市","120000 天津市","130000 河北省","140000 山西省","150000 内蒙古自治区","210000 辽宁省","220000 吉林省","230000 黑龙江省","310000 上海市","320000 江苏省","330000 浙江省","340000 安徽省","350000 福建省","360000 江西省","370000 山东省","410000 河南省","420000 湖北省","430000 湖南省","440000 广东省","450000 广西壮族自治区","460000 海南省","500000 重庆市","510000 四川省","520000 贵州省","530000 云南省","540000 西藏自治区","610000 陕西省","620000 甘肃省","630000 青海省","640000 宁夏回族自治区","650000 新疆维吾尔自治区","650000 新疆维吾尔自治区","710000 台湾省","810000 香港特别行政区","820000 澳门特别行政区"],region:function(){return this.pick(this.regions).split(" ")[1]},address:function(){},city:function(){},phone:function(){},areacode:function(){},street:function(){},street_suffixes:function(){},street_suffix:function(){},states:function(){},state:function(){},zip:function(a){for(var b="",c=0;(a||6)>c;c++)b+=this.natural(0,9);return b}}),b.extend({todo:function(){return"todo"}}),b.extend({d4:function(){return this.natural(1,4)},d6:function(){return this.natural(1,6)},d8:function(){return this.natural(1,8)},d12:function(){return this.natural(1,12)},d20:function(){return this.natural(1,20)},d100:function(){return this.natural(1,100)},guid:function(){var a="ABCDEF1234567890",b=this.string(a,8)+"-"+this.string(a,4)+"-"+this.string(a,4)+"-"+this.string(a,4)+"-"+this.string(a,12);return b},id:function(){var a,b=0,c=["7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2"],d=["1","0","X","9","8","7","6","5","4","3","2"];a=this.pick(this.regions).split(" ")[0]+this.date("yyyyMMdd")+this.string("number",3);for(var e=0;e1)e=d.pick(h.gen(a.template));else for(b=0;b",g.rurl);var h=b.mock(g.template);return console.log("[mock]",h),e.success&&e.success(h,"success",d),e.complete&&e.complete(h,"success",d),a}}return c.apply(this,arguments)};for(var e in c)a.io[e]=c[e]}),b.Util=c,b.Random=d,b.heredoc=c.heredoc,"object"==typeof module&&module.exports?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):"function"==typeof define&&define.cmd&&define(function(){return b}),this.Mock=b,this.Random=d,"undefined"!=typeof KISSY&&c.each(["mock","components/mock/index","mock/dist/mock","gallery/Mock/0.1.1/index","gallery/Mock/0.1.2/index"],function(a){KISSY.add(a,function(a){return b.mockjax(a),b},{requires:["ajax"]})}),function(a){var e={version:"0.0.1"};this.Mock||(module.exports=e),b.tpl=function(a,b,c,d){return e.mock(a,b,c,d)},b.parse=function(a){return Handlebars.parse(a)},e.mock=function(a,b,d,e){return d=d?c.extend({},d,Handlebars.helpers):Handlebars.helpers,e=e?c.extend({},e,Handlebars.partials):Handlebars.partials,f.gen(a,null,b,d,e)};var f={debug:e.debug||!1,extend:c.extend};f.gen=function(a,b,d,g,h){if(c.isString(a)){var i=Handlebars.parse(a);d=f.parseOptions(a,d);var j=f.gen(i,b,d,g,h);return j}if(b=b||[{}],d=d||{},this[a.type]!==c.noop){d.__path=d.__path||[],(e.debug||f.debug)&&(console.log(),console.group("["+a.type+"]",JSON.stringify(a)),console.log("[options]",d.__path.length,JSON.stringify(d)));var k=d.__path.length;return this[a.type](a,b,d,g,h),d.__path.splice(k),(e.debug||f.debug)&&console.groupEnd(),b[b.length-1]}},f.parseOptions=function(a,b){var d,e,f,g=//g,h=a.match(g),i={};for(d=0;h&&di&&b.splice(0,b.length-i)},f.block=function(a,b,e,f,h){var i,j,k,l,m,n=a.mustache.id.parts,o=b[0],p=b.length;if(a.inverse,a.mustache.isHelper||f&&f[a.mustache.id.string])m=n[0],l=(g[m]||g.custom).apply(this,arguments),o=b[0];else for(i=0;ii;i++)o.push("undefined"!=typeof l[i]?l[i]:{}),e.__path.push("[]"),b.unshift(o[o.length-1]),this.gen(a.program,b,e,f,h),e.__path.pop(),b.shift();else this.gen(a.program,b,e,f,h);b.length>p&&b.splice(0,b.length-p)},f.hash=function(a,b,c,d,e){var f,g,h,i=a.pairs;for(g=0;ge;e++)d.__path.push(n[e]),g=n[e],h=n[e-1],m=d[h],i=e===f-1?o[g]:{},j=this.val(g,d,b,i),k=c.type(o[g]),l=c.type(j),"undefined"===k?o[g]=f-1>e&&"object"!==l&&"array"!==l?{}:c.isArray(j)&&[]||j:f-1>e&&"object"!==k&&"array"!==k&&(o[g]=c.isArray(j)&&[]||{}),k=c.type(o[g]),("object"===k||"array"===k)&&(o=o[g],b.unshift(o));else;b.length>p&&b.splice(0,b.length-p)},f.partial=function(a,b,c,d,e){var g=a.partialName.name,h=e&&e[g],i=b.length;h&&f.gen(h,b,c,d,e),b.length>i&&b.splice(0,b.length-i)},f.content=c.noop,f.PARTIAL_NAME=c.noop,f.DATA=c.noop,f.STRING=c.noop,f.INTEGER=c.noop,f.BOOLEAN=c.noop,f.comment=c.noop;var g={};g.each=function(a,b,d){var e,f,g,h,i,j,k,l=b[0];for(i=a.mustache.params[0].parts,e=0,f=i.length;f>e;e++)d.__path.push(i[e]),g=i[e],j=e===f-1?[]:{},h=this.val(g,d,b,j),l[g]=c.isArray(h)&&[]||h,k=c.type(l[g]),("object"===k||"array"===k)&&(l=l[g],b.unshift(l));return h},g["if"]=g.unless=function(a,b,d){var e,f,g,h,i,j,k,l=a.mustache.params,m=b[0];for(e=0;ee;e++)d.__path.push(i[e]),g=i[e],j=e===f-1?[]:{},h=this.val(g,d,b,j),l[g]=c.isArray(h)&&[]||h,k=c.type(l[g]),("object"===k||"array"===k)&&(l=l[g],b.unshift(l));return h}}}.call(this),function(a){if("undefined"!=typeof KISSY){var e,f={debug:!1};KISSY.use("xtemplate",function(a,b){e=b}),this.Mock||(module.exports=f),b.xtpl=function(a,b,c,d){return f.mock(a,b,c,d)},b.xparse=function(a){return e.compiler.parse(a)},f.mock=function(a,b,d,f){return d=d?c.extend({},d,e.RunTime.commands):e.RunTime.commands,f=f?c.extend({},f,e.RunTime.subTpls):e.RunTime.subTpls,this.gen(a,null,b,d,f,{})},f.parse=function(a){return e.compiler.parse(a)},f.gen=function(a,b,d,e,g,h){if("string"==typeof a){f.debug&&console.log("[tpl ]\n",a);var i=this.parse(a);d=this.parseOptions(a,d);var j=this.gen(i,b,d,e,g,h);return j}if(b=b||[{}],d=d||{},a.type=a.type,this[a.type]!==c.noop){d.__path=d.__path||[],f.debug&&(console.log(),console.group("["+a.type+"]",JSON.stringify(a)),console.log("[context]","[before]",b.length,JSON.stringify(b)),console.log("[options]","[before]",d.__path.length,JSON.stringify(d)),console.log("[other ]","[before]",JSON.stringify(h)));var k=d.__path.length;return this[a.type](a,b,d,e,g,h),f.debug&&console.log("[__path ]","[after ]",d.__path),(!h.hold||"function"==typeof h.hold&&!h.hold(a,d,b))&&d.__path.splice(k),f.debug&&(console.log("[context]","[after ]",b.length,JSON.stringify(b)),console.groupEnd()),b[b.length-1]}},f.parseOptions=function(a,b){var d,e,f,g=//g,h=a.match(g),i={};for(d=0;h&&d0)return j[0];if(d in i)return i[d]}return c.isArray(g[0])?{}:h!==a?h:d},f.program=function(a,b,c,d,e,f){for(var g=0;gl;l++)n.push(k&&k[l]!==a?k[l]:{}),f.__path.push(l),e.unshift(n[n.length-1]),this.gen(b.program,e,f,g,h,i),f.__path.pop(),e.shift();else this.gen(b.program,e,f,g,h,i);(!i.hold||"function"==typeof i.hold&&!i.hold(b,f,e))&&e.splice(0,e.length-j)},f.tpl=function(a,b,d,e,f,g){if(a.params&&a.params.length){g=c.extend({},g,{def:{each:[],"if":"@BOOL(2,1,true)",unless:"@BOOL(2,1,false)","with":{}}[a.path.string],hold:{each:!0,"if":function(a,b,c,d,e){return"object"==typeof e},unless:function(a,b,c,d,e){return"object"==typeof e},"with":!0,include:!1}[a.path.string]});for(var h,i=0;i-1?d.float(-Math.pow(10,10),Math.pow(10,10),1,Math.pow(10,6)):d.integer():a}()})),this.gen(b.op2,e,f,g,h,c.extend({},i,{def:function(){return"number"===b.op1.type?b.op1.value.indexOf(".")>-1?d.float(-Math.pow(10,10),Math.pow(10,10),1,Math.pow(10,6)):d.integer():a}()}))},f.relationalExpression=function(a,b,c,d,e,f){this.gen(a.op1,b,c,d,e,f),this.gen(a.op2,b,c,d,e,f)},f.equalityExpression=c.noop,f.conditionalAndExpression=c.noop,f.conditionalOrExpression=c.noop,f.string=c.noop,f.number=c.noop,f.boolean=c.noop,f.hash=function(a,b,c,d,e,f){var g,h=a.value;for(g in h)this.gen(h[g],b,c,d,e,f)},f.id=function(b,d,e,g,h,i){function j(a,b,d,e,f){var g=c.type(a[e]),h=c.type(f);return f="true"===f?!0:"false"===f?!1:f,"undefined"===g?a[e]=d-1>b&&!c.isObjectOrArray(f)?{}:c.isArray(f)&&[]||f:d-1>b&&"object"!==g&&"array"!==g?a[e]=c.isArray(f)&&[]||{}:"object"!==g&&"array"!==g&&"object"!==h&&"array"!==h&&(a[e]=f),a[e]}var k,l,m,n,o,p=d.length,q=b.parts,r=d[b.depth];for(c.isArray(r)&&(r=d[b.depth+1]),k=0,l=q.length;l>k;k++)(0!==k||"this"!==q[k])&&(/^(xindex|xcount|xkey)$/.test(q[k])||0===k&&1===l&&q[k]in g||(e.__path.push(q[k]),m=q[k],n=k===l-1?i.def!==a?i.def:d[0][m]:{},o=this.val(m,e,d,n),f.debug&&(console.log("[def ]",JSON.stringify(n)),console.log("[val ]",JSON.stringify(o))),o=j(r,k,l,m,o),c.isObjectOrArray(r[m])&&d.unshift(r=r[m])));(!i.hold||"function"==typeof i.hold&&!i.hold(b,e,d,m,o))&&d.splice(0,d.length-p)}}}.call(this)}).call(this); -//# sourceMappingURL=dist/mock-min.map +/*! mockjs 13-04-2015 14:32:27 */ +/*! src/mock-prefix.js */ +/*! + Mock - 模拟请求 & 模拟数据 + https://github.com/nuysoft/Mock + 墨智 nuysoft@gmail.com + */ +(function(undefined) { + var Mock = { + version: "0.1.9", + _mocked: {} + }; + /*! src/util.js */ + var Util = function() { + var Util = {}; + Util.extend = function extend() { + var target = arguments[0] || {}, i = 1, length = arguments.length, options, name, src, copy, clone; + if (length === 1) { + target = this; + i = 0; + } + for (;i < length; i++) { + options = arguments[i]; + if (!options) continue; + for (name in options) { + src = target[name]; + copy = options[name]; + if (target === copy) continue; + if (copy === undefined) continue; + if (Util.isArray(copy) || Util.isObject(copy)) { + if (Util.isArray(copy)) clone = src && Util.isArray(src) ? src : []; + if (Util.isObject(copy)) clone = src && Util.isObject(src) ? src : {}; + target[name] = Util.extend(clone, copy); + } else { + target[name] = copy; + } + } + } + return target; + }; + Util.each = function each(obj, iterator, context) { + var i, key; + if (this.type(obj) === "number") { + for (i = 0; i < obj; i++) { + iterator(i, i); + } + } else if (obj.length === +obj.length) { + for (i = 0; i < obj.length; i++) { + if (iterator.call(context, obj[i], i, obj) === false) break; + } + } else { + for (key in obj) { + if (iterator.call(context, obj[key], key, obj) === false) break; + } + } + }; + Util.type = function type(obj) { + return obj === null || obj === undefined ? String(obj) : Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1].toLowerCase(); + }; + Util.each("String Object Array RegExp Function".split(" "), function(value) { + Util["is" + value] = function(obj) { + return Util.type(obj) === value.toLowerCase(); + }; + }); + Util.isObjectOrArray = function(value) { + return Util.isObject(value) || Util.isArray(value); + }; + Util.isNumeric = function(value) { + return !isNaN(parseFloat(value)) && isFinite(value); + }; + Util.keys = function(obj) { + var keys = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) keys.push(key); + } + return keys; + }; + Util.values = function(obj) { + var values = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) values.push(obj[key]); + } + return values; + }; + Util.heredoc = function heredoc(fn) { + return fn.toString().replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, "").replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""); + }; + Util.noop = function() {}; + return Util; + }(); + /*! src/random.js */ + var Random = function() { + var Random = { + extend: Util.extend + }; + Random.extend({ + "boolean": function(min, max, cur) { + if (cur !== undefined) { + min = typeof min !== "undefined" && !isNaN(min) ? parseInt(min, 10) : 1; + max = typeof max !== "undefined" && !isNaN(max) ? parseInt(max, 10) : 1; + return Math.random() > 1 / (min + max) * min ? !cur : cur; + } + return Math.random() >= .5; + }, + bool: function(min, max, cur) { + return this.boolean(min, max, cur); + }, + natural: function(min, max) { + min = typeof min !== "undefined" ? parseInt(min, 10) : 0; + max = typeof max !== "undefined" ? parseInt(max, 10) : 9007199254740992; + return Math.round(Math.random() * (max - min)) + min; + }, + integer: function(min, max) { + min = typeof min !== "undefined" ? parseInt(min, 10) : -9007199254740992; + max = typeof max !== "undefined" ? parseInt(max, 10) : 9007199254740992; + return Math.round(Math.random() * (max - min)) + min; + }, + "int": function(min, max) { + return this.integer(min, max); + }, + "float": function(min, max, dmin, dmax) { + dmin = dmin === undefined ? 0 : dmin; + dmin = Math.max(Math.min(dmin, 17), 0); + dmax = dmax === undefined ? 17 : dmax; + dmax = Math.max(Math.min(dmax, 17), 0); + var ret = this.integer(min, max) + "."; + for (var i = 0, dcount = this.natural(dmin, dmax); i < dcount; i++) { + ret += this.character("number"); + } + return parseFloat(ret, 10); + }, + character: function(pool) { + var pools = { + lower: "abcdefghijklmnopqrstuvwxyz", + upper: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + number: "0123456789", + symbol: "!@#$%^&*()[]" + }; + pools.alpha = pools.lower + pools.upper; + pools["undefined"] = pools.lower + pools.upper + pools.number + pools.symbol; + pool = pools[("" + pool).toLowerCase()] || pool; + return pool.charAt(Random.natural(0, pool.length - 1)); + }, + "char": function(pool) { + return this.character(pool); + }, + string: function(pool, min, max) { + var length; + if (arguments.length === 3) { + length = Random.natural(min, max); + } + if (arguments.length === 2) { + if (typeof arguments[0] === "string") { + length = min; + } else { + length = Random.natural(pool, min); + pool = undefined; + } + } + if (arguments.length === 1) { + length = pool; + pool = undefined; + } + if (arguments.length === 0) { + length = Random.natural(3, 7); + } + var text = ""; + for (var i = 0; i < length; i++) { + text += Random.character(pool); + } + return text; + }, + str: function(pool, min, max) { + return this.string(pool, min, max); + }, + range: function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + start = +start, stop = +stop, step = +step; + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + while (idx < len) { + range[idx++] = start; + start += step; + } + return range; + } + }); + Random.extend({ + patternLetters: { + yyyy: "getFullYear", + yy: function(date) { + return ("" + date.getFullYear()).slice(2); + }, + y: "yy", + MM: function(date) { + var m = date.getMonth() + 1; + return m < 10 ? "0" + m : m; + }, + M: function(date) { + return date.getMonth() + 1; + }, + dd: function(date) { + var d = date.getDate(); + return d < 10 ? "0" + d : d; + }, + d: "getDate", + HH: function(date) { + var h = date.getHours(); + return h < 10 ? "0" + h : h; + }, + H: "getHours", + hh: function(date) { + var h = date.getHours() % 12; + return h < 10 ? "0" + h : h; + }, + h: function(date) { + return date.getHours() % 12; + }, + mm: function(date) { + var m = date.getMinutes(); + return m < 10 ? "0" + m : m; + }, + m: "getMinutes", + ss: function(date) { + var s = date.getSeconds(); + return s < 10 ? "0" + s : s; + }, + s: "getSeconds", + SS: function(date) { + var ms = date.getMilliseconds(); + return ms < 10 && "00" + ms || ms < 100 && "0" + ms || ms; + }, + S: "getMilliseconds", + A: function(date) { + return date.getHours() < 12 ? "AM" : "PM"; + }, + a: function(date) { + return date.getHours() < 12 ? "am" : "pm"; + }, + T: "getTime" + } + }); + Random.extend({ + rformat: new RegExp(function() { + var re = []; + for (var i in Random.patternLetters) re.push(i); + return "(" + re.join("|") + ")"; + }(), "g"), + format: function(date, format) { + var patternLetters = Random.patternLetters, rformat = Random.rformat; + return format.replace(rformat, function($0, flag) { + return typeof patternLetters[flag] === "function" ? patternLetters[flag](date) : patternLetters[flag] in patternLetters ? arguments.callee($0, patternLetters[flag]) : date[patternLetters[flag]](); + }); + }, + randomDate: function(min, max) { + min = min === undefined ? new Date(0) : min; + max = max === undefined ? new Date() : max; + return new Date(Math.random() * (max.getTime() - min.getTime())); + }, + date: function(format) { + format = format || "yyyy-MM-dd"; + return this.format(this.randomDate(), format); + }, + time: function(format) { + format = format || "HH:mm:ss"; + return this.format(this.randomDate(), format); + }, + datetime: function(format) { + format = format || "yyyy-MM-dd HH:mm:ss"; + return this.format(this.randomDate(), format); + }, + now: function(unit, format) { + if (arguments.length === 1) { + if (!/year|month|week|day|hour|minute|second|week/.test(unit)) { + format = unit; + unit = ""; + } + } + unit = (unit || "").toLowerCase(); + format = format || "yyyy-MM-dd HH:mm:ss"; + var date = new Date(); + switch (unit) { + case "year": + date.setMonth(0); + + case "month": + date.setDate(1); + + case "week": + case "day": + date.setHours(0); + + case "hour": + date.setMinutes(0); + + case "minute": + date.setSeconds(0); + + case "second": + date.setMilliseconds(0); + } + switch (unit) { + case "week": + date.setDate(date.getDate() - date.getDay()); + } + return this.format(date, format); + } + }); + Random.extend({ + ad_size: [ "300x250", "250x250", "240x400", "336x280", "180x150", "720x300", "468x60", "234x60", "88x31", "120x90", "120x60", "120x240", "125x125", "728x90", "160x600", "120x600", "300x600" ], + screen_size: [ "320x200", "320x240", "640x480", "800x480", "800x480", "1024x600", "1024x768", "1280x800", "1440x900", "1920x1200", "2560x1600" ], + video_size: [ "720x480", "768x576", "1280x720", "1920x1080" ], + image: function(size, background, foreground, format, text) { + if (arguments.length === 4) { + text = format; + format = undefined; + } + if (arguments.length === 3) { + text = foreground; + foreground = undefined; + } + if (!size) size = this.pick(this.ad_size); + if (background && ~background.indexOf("#")) background = background.slice(1); + if (foreground && ~foreground.indexOf("#")) foreground = foreground.slice(1); + return "http://dummyimage.com/" + size + (background ? "/" + background : "") + (foreground ? "/" + foreground : "") + (format ? "." + format : "") + (text ? "&text=" + text : ""); + }, + img: function() { + return this.image.apply(this, arguments); + } + }); + Random.extend({ + brandColors: { + "4ormat": "#fb0a2a", + "500px": "#02adea", + "About.me (blue)": "#00405d", + "About.me (yellow)": "#ffcc33", + Addvocate: "#ff6138", + Adobe: "#ff0000", + Aim: "#fcd20b", + Amazon: "#e47911", + Android: "#a4c639", + "Angie's List": "#7fbb00", + AOL: "#0060a3", + Atlassian: "#003366", + Behance: "#053eff", + "Big Cartel": "#97b538", + bitly: "#ee6123", + Blogger: "#fc4f08", + Boeing: "#0039a6", + "Booking.com": "#003580", + Carbonmade: "#613854", + Cheddar: "#ff7243", + "Code School": "#3d4944", + Delicious: "#205cc0", + Dell: "#3287c1", + Designmoo: "#e54a4f", + Deviantart: "#4e6252", + "Designer News": "#2d72da", + Devour: "#fd0001", + DEWALT: "#febd17", + "Disqus (blue)": "#59a3fc", + "Disqus (orange)": "#db7132", + Dribbble: "#ea4c89", + Dropbox: "#3d9ae8", + Drupal: "#0c76ab", + Dunked: "#2a323a", + eBay: "#89c507", + Ember: "#f05e1b", + Engadget: "#00bdf6", + Envato: "#528036", + Etsy: "#eb6d20", + Evernote: "#5ba525", + "Fab.com": "#dd0017", + Facebook: "#3b5998", + Firefox: "#e66000", + "Flickr (blue)": "#0063dc", + "Flickr (pink)": "#ff0084", + Forrst: "#5b9a68", + Foursquare: "#25a0ca", + Garmin: "#007cc3", + GetGlue: "#2d75a2", + Gimmebar: "#f70078", + GitHub: "#171515", + "Google Blue": "#0140ca", + "Google Green": "#16a61e", + "Google Red": "#dd1812", + "Google Yellow": "#fcca03", + "Google+": "#dd4b39", + Grooveshark: "#f77f00", + Groupon: "#82b548", + "Hacker News": "#ff6600", + HelloWallet: "#0085ca", + "Heroku (light)": "#c7c5e6", + "Heroku (dark)": "#6567a5", + HootSuite: "#003366", + Houzz: "#73ba37", + HTML5: "#ec6231", + IKEA: "#ffcc33", + IMDb: "#f3ce13", + Instagram: "#3f729b", + Intel: "#0071c5", + Intuit: "#365ebf", + Kickstarter: "#76cc1e", + kippt: "#e03500", + Kodery: "#00af81", + LastFM: "#c3000d", + LinkedIn: "#0e76a8", + Livestream: "#cf0005", + Lumo: "#576396", + Mixpanel: "#a086d3", + Meetup: "#e51937", + Nokia: "#183693", + NVIDIA: "#76b900", + Opera: "#cc0f16", + Path: "#e41f11", + "PayPal (dark)": "#1e477a", + "PayPal (light)": "#3b7bbf", + Pinboard: "#0000e6", + Pinterest: "#c8232c", + PlayStation: "#665cbe", + Pocket: "#ee4056", + Prezi: "#318bff", + Pusha: "#0f71b4", + Quora: "#a82400", + "QUOTE.fm": "#66ceff", + Rdio: "#008fd5", + Readability: "#9c0000", + "Red Hat": "#cc0000", + Resource: "#7eb400", + Rockpack: "#0ba6ab", + Roon: "#62b0d9", + RSS: "#ee802f", + Salesforce: "#1798c1", + Samsung: "#0c4da2", + Shopify: "#96bf48", + Skype: "#00aff0", + Snagajob: "#f47a20", + Softonic: "#008ace", + SoundCloud: "#ff7700", + "Space Box": "#f86960", + Spotify: "#81b71a", + Sprint: "#fee100", + Squarespace: "#121212", + StackOverflow: "#ef8236", + Staples: "#cc0000", + "Status Chart": "#d7584f", + Stripe: "#008cdd", + StudyBlue: "#00afe1", + StumbleUpon: "#f74425", + "T-Mobile": "#ea0a8e", + Technorati: "#40a800", + "The Next Web": "#ef4423", + Treehouse: "#5cb868", + Trulia: "#5eab1f", + Tumblr: "#34526f", + "Twitch.tv": "#6441a5", + Twitter: "#00acee", + TYPO3: "#ff8700", + Ubuntu: "#dd4814", + Ustream: "#3388ff", + Verizon: "#ef1d1d", + Vimeo: "#86c9ef", + Vine: "#00a478", + Virb: "#06afd8", + "Virgin Media": "#cc0000", + Wooga: "#5b009c", + "WordPress (blue)": "#21759b", + "WordPress (orange)": "#d54e21", + "WordPress (grey)": "#464646", + Wunderlist: "#2b88d9", + XBOX: "#9bc848", + XING: "#126567", + "Yahoo!": "#720e9e", + Yandex: "#ffcc00", + Yelp: "#c41200", + YouTube: "#c4302b", + Zalongo: "#5498dc", + Zendesk: "#78a300", + Zerply: "#9dcc7a", + Zootool: "#5e8b1d" + }, + brands: function() { + var brands = []; + for (var b in this.brandColors) { + brands.push(b); + } + return brands; + }, + dataImage: function(size, text) { + var canvas = typeof document !== "undefined" && document.createElement("canvas"), ctx = canvas && canvas.getContext && canvas.getContext("2d"); + if (!canvas || !ctx) return ""; + if (!size) size = this.pick(this.ad_size); + text = text !== undefined ? text : size; + size = size.split("x"); + var width = parseInt(size[0], 10), height = parseInt(size[1], 10), background = this.brandColors[this.pick(this.brands())], foreground = "#FFF", text_height = 14, font = "sans-serif"; + canvas.width = width; + canvas.height = height; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillStyle = background; + ctx.fillRect(0, 0, width, height); + ctx.fillStyle = foreground; + ctx.font = "bold " + text_height + "px " + font; + ctx.fillText(text, width / 2, height / 2, width); + return canvas.toDataURL("image/png"); + } + }); + Random.extend({ + color: function() { + var colour = Math.floor(Math.random() * (16 * 16 * 16 * 16 * 16 * 16 - 1)).toString(16); + colour = "#" + ("000000" + colour).slice(-6); + return colour; + } + }); + Random.extend({ + capitalize: function(word) { + return (word + "").charAt(0).toUpperCase() + (word + "").substr(1); + }, + upper: function(str) { + return (str + "").toUpperCase(); + }, + lower: function(str) { + return (str + "").toLowerCase(); + }, + pick: function(arr) { + arr = arr || []; + return arr[this.natural(0, arr.length - 1)]; + }, + shuffle: function(arr) { + arr = arr || []; + var old = arr.slice(0), result = [], index = 0, length = old.length; + for (var i = 0; i < length; i++) { + index = this.natural(0, old.length - 1); + result.push(old[index]); + old.splice(index, 1); + } + return result; + } + }); + Random.extend({ + paragraph: function(min, max) { + var len; + if (arguments.length === 0) len = Random.natural(3, 7); + if (arguments.length === 1) len = max = min; + if (arguments.length === 2) { + min = parseInt(min, 10); + max = parseInt(max, 10); + len = Random.natural(min, max); + } + var arr = []; + for (var i = 0; i < len; i++) { + arr.push(Random.sentence()); + } + return arr.join(" "); + }, + sentence: function(min, max) { + var len; + if (arguments.length === 0) len = Random.natural(12, 18); + if (arguments.length === 1) len = max = min; + if (arguments.length === 2) { + min = parseInt(min, 10); + max = parseInt(max, 10); + len = Random.natural(min, max); + } + var arr = []; + for (var i = 0; i < len; i++) { + arr.push(Random.word()); + } + return Random.capitalize(arr.join(" ")) + "."; + }, + word: function(min, max) { + var len; + if (arguments.length === 0) len = Random.natural(3, 10); + if (arguments.length === 1) len = max = min; + if (arguments.length === 2) { + min = parseInt(min, 10); + max = parseInt(max, 10); + len = Random.natural(min, max); + } + var result = ""; + for (var i = 0; i < len; i++) { + result += Random.character("lower"); + } + return result; + }, + title: function(min, max) { + var len, result = []; + if (arguments.length === 0) len = Random.natural(3, 7); + if (arguments.length === 1) len = max = min; + if (arguments.length === 2) { + min = parseInt(min, 10); + max = parseInt(max, 10); + len = Random.natural(min, max); + } + for (var i = 0; i < len; i++) { + result.push(this.capitalize(this.word())); + } + return result.join(" "); + } + }); + Random.extend({ + first: function() { + var names = [ "James", "John", "Robert", "Michael", "William", "David", "Richard", "Charles", "Joseph", "Thomas", "Christopher", "Daniel", "Paul", "Mark", "Donald", "George", "Kenneth", "Steven", "Edward", "Brian", "Ronald", "Anthony", "Kevin", "Jason", "Matthew", "Gary", "Timothy", "Jose", "Larry", "Jeffrey", "Frank", "Scott", "Eric" ].concat([ "Mary", "Patricia", "Linda", "Barbara", "Elizabeth", "Jennifer", "Maria", "Susan", "Margaret", "Dorothy", "Lisa", "Nancy", "Karen", "Betty", "Helen", "Sandra", "Donna", "Carol", "Ruth", "Sharon", "Michelle", "Laura", "Sarah", "Kimberly", "Deborah", "Jessica", "Shirley", "Cynthia", "Angela", "Melissa", "Brenda", "Amy", "Anna" ]); + return this.pick(names); + }, + last: function() { + var names = [ "Smith", "Johnson", "Williams", "Brown", "Jones", "Miller", "Davis", "Garcia", "Rodriguez", "Wilson", "Martinez", "Anderson", "Taylor", "Thomas", "Hernandez", "Moore", "Martin", "Jackson", "Thompson", "White", "Lopez", "Lee", "Gonzalez", "Harris", "Clark", "Lewis", "Robinson", "Walker", "Perez", "Hall", "Young", "Allen" ]; + return this.pick(names); + }, + name: function(middle) { + return this.first() + " " + (middle ? this.first() + " " : "") + this.last(); + }, + chineseName: function(count) { + var familyNames = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐".split(""); + var names = "贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓".split(""); + if (typeof count !== "number") { + count = Math.random() > .66 ? 2 : 3; + } + var familyName = this.pick(familyNames); + var name = ""; + for (var i = 0; i < count; i++) { + name += this.pick(names); + } + return familyName + name; + } + }); + Random.extend({ + url: function() { + return "http://" + this.domain() + "/" + this.word(); + }, + domain: function(tld) { + return this.word() + "." + (tld || this.tld()); + }, + email: function(domain) { + return this.character("lower") + "." + this.last().toLowerCase() + "@" + this.last().toLowerCase() + "." + this.tld(); + }, + ip: function() { + return this.natural(0, 255) + "." + this.natural(0, 255) + "." + this.natural(0, 255) + "." + this.natural(0, 255); + }, + tlds: [ "com", "org", "edu", "gov", "co.uk", "net", "io" ], + tld: function() { + return this.pick(this.tlds); + } + }); + Random.extend({ + areas: [ "东北", "华北", "华东", "华中", "华南", "西南", "西北" ], + area: function() { + return this.pick(this.areas); + }, + regions: [ "110000 北京市", "120000 天津市", "130000 河北省", "140000 山西省", "150000 内蒙古自治区", "210000 辽宁省", "220000 吉林省", "230000 黑龙江省", "310000 上海市", "320000 江苏省", "330000 浙江省", "340000 安徽省", "350000 福建省", "360000 江西省", "370000 山东省", "410000 河南省", "420000 湖北省", "430000 湖南省", "440000 广东省", "450000 广西壮族自治区", "460000 海南省", "500000 重庆市", "510000 四川省", "520000 贵州省", "530000 云南省", "540000 西藏自治区", "610000 陕西省", "620000 甘肃省", "630000 青海省", "640000 宁夏回族自治区", "650000 新疆维吾尔自治区", "650000 新疆维吾尔自治区", "710000 台湾省", "810000 香港特别行政区", "820000 澳门特别行政区" ], + region: function() { + return this.pick(this.regions).split(" ")[1]; + }, + address: function() {}, + city: function() {}, + phone: function() {}, + areacode: function() {}, + street: function() {}, + street_suffixes: function() {}, + street_suffix: function() {}, + states: function() {}, + state: function() {}, + zip: function(len) { + var zip = ""; + for (var i = 0; i < (len || 6); i++) zip += this.natural(0, 9); + return zip; + } + }); + Random.extend({ + todo: function() { + return "todo"; + } + }); + Random.extend({ + d4: function() { + return this.natural(1, 4); + }, + d6: function() { + return this.natural(1, 6); + }, + d8: function() { + return this.natural(1, 8); + }, + d12: function() { + return this.natural(1, 12); + }, + d20: function() { + return this.natural(1, 20); + }, + d100: function() { + return this.natural(1, 100); + }, + guid: function() { + var pool = "ABCDEF1234567890", guid = this.string(pool, 8) + "-" + this.string(pool, 4) + "-" + this.string(pool, 4) + "-" + this.string(pool, 4) + "-" + this.string(pool, 12); + return guid; + }, + id: function() { + var id, sum = 0, rank = [ "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2" ], last = [ "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" ]; + id = this.pick(this.regions).split(" ")[0] + this.date("yyyyMMdd") + this.string("number", 3); + for (var i = 0; i < id.length; i++) { + sum += id[i] * rank[i]; + } + id += last[sum % 11]; + return id; + }, + autoIncrementInteger: 0, + increment: function(step) { + return this.autoIncrementInteger += +step || 1; + }, + inc: function(step) { + return this.increment(step); + } + }); + return Random; + }(); + /*! src/mock.js */ + var rkey = /(.+)\|(?:\+(\d+)|([\+\-]?\d+-?[\+\-]?\d*)?(?:\.(\d+-?\d*))?)/, rrange = /([\+\-]?\d+)-?([\+\-]?\d+)?/, rplaceholder = /\\*@([^@#%&()\?\s\/\.]+)(?:\((.*?)\))?/g; + Mock.extend = Util.extend; + Mock.mock = function(rurl, rtype, template) { + if (arguments.length === 1) { + return Handle.gen(rurl); + } + if (arguments.length === 2) { + template = rtype; + rtype = undefined; + } + Mock._mocked[rurl + (rtype || "")] = { + rurl: rurl, + rtype: rtype, + template: template + }; + return Mock; + }; + var Handle = { + extend: Util.extend + }; + Handle.rule = function(name) { + name = (name || "") + ""; + var parameters = (name || "").match(rkey), range = parameters && parameters[3] && parameters[3].match(rrange), min = range && parseInt(range[1], 10), max = range && parseInt(range[2], 10), count = range ? !range[2] && parseInt(range[1], 10) || Random.integer(min, max) : 1, decimal = parameters && parameters[4] && parameters[4].match(rrange), dmin = decimal && parseInt(decimal[1], 10), dmax = decimal && parseInt(decimal[2], 10), dcount = decimal ? !decimal[2] && parseInt(decimal[1], 10) || Random.integer(dmin, dmax) : 0, point = parameters && parameters[4]; + return { + parameters: parameters, + range: range, + min: min, + max: max, + count: count, + decimal: decimal, + dmin: dmin, + dmax: dmax, + dcount: dcount, + point: point + }; + }; + Handle.gen = function(template, name, context) { + name = name = (name || "") + ""; + context = context || {}; + context = { + path: context.path || [], + templatePath: context.templatePath || [], + currentContext: context.currentContext, + templateCurrentContext: context.templateCurrentContext || template, + root: context.root, + templateRoot: context.templateRoot + }; + var rule = Handle.rule(name); + var type = Util.type(template); + if (Handle[type]) { + return Handle[type]({ + type: type, + template: template, + name: name, + parsedName: name ? name.replace(rkey, "$1") : name, + rule: rule, + context: context + }); + } + return template; + }; + Handle.extend({ + array: function(options) { + var result = [], i, j; + if (!options.rule.parameters) { + for (i = 0; i < options.template.length; i++) { + options.context.path.push(i); + result.push(Handle.gen(options.template[i], i, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + })); + options.context.path.pop(); + } + } else { + if (options.rule.count === 1 && options.template.length > 1) { + options.context.path.push(options.name); + result = Random.pick(Handle.gen(options.template, undefined, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + })); + options.context.path.pop(); + } else { + for (i = 0; i < options.rule.count; i++) { + j = 0; + do { + result.push(Handle.gen(options.template[j++])); + } while (j < options.template.length); + } + } + } + return result; + }, + object: function(options) { + var result = {}, keys, fnKeys, key, parsedKey, inc, i; + if (options.rule.min) { + keys = Util.keys(options.template); + keys = Random.shuffle(keys); + keys = keys.slice(0, options.rule.count); + for (i = 0; i < keys.length; i++) { + key = keys[i]; + parsedKey = key.replace(rkey, "$1"); + options.context.path.push(parsedKey); + result[parsedKey] = Handle.gen(options.template[key], key, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + }); + options.context.path.pop(); + } + } else { + keys = []; + fnKeys = []; + for (key in options.template) { + (typeof options.template[key] === "function" ? fnKeys : keys).push(key); + } + keys = keys.concat(fnKeys); + for (i = 0; i < keys.length; i++) { + key = keys[i]; + parsedKey = key.replace(rkey, "$1"); + options.context.path.push(parsedKey); + result[parsedKey] = Handle.gen(options.template[key], key, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + }); + options.context.path.pop(); + inc = key.match(rkey); + if (inc && inc[2] && Util.type(options.template[key]) === "number") { + options.template[key] += parseInt(inc[2], 10); + } + } + } + return result; + }, + number: function(options) { + var result, parts, i; + if (options.rule.point) { + options.template += ""; + parts = options.template.split("."); + parts[0] = options.rule.range ? options.rule.count : parts[0]; + parts[1] = (parts[1] || "").slice(0, options.rule.dcount); + for (i = 0; parts[1].length < options.rule.dcount; i++) { + parts[1] += Random.character("number"); + } + result = parseFloat(parts.join("."), 10); + } else { + result = options.rule.range && !options.rule.parameters[2] ? options.rule.count : options.template; + } + return result; + }, + "boolean": function(options) { + var result; + result = options.rule.parameters ? Random.bool(options.rule.min, options.rule.max, options.template) : options.template; + return result; + }, + string: function(options) { + var result = "", i, placeholders, ph, phed; + if (options.template.length) { + for (i = 0; i < options.rule.count; i++) { + result += options.template; + } + placeholders = result.match(rplaceholder) || []; + for (i = 0; i < placeholders.length; i++) { + ph = placeholders[i]; + if (/^\\/.test(ph)) { + placeholders.splice(i--, 1); + continue; + } + phed = Handle.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext); + if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { + result = phed; + break; + } + result = result.replace(ph, phed); + } + } else { + result = options.rule.range ? Random.string(options.rule.count) : options.template; + } + return result; + }, + "function": function(options) { + return options.template.call(options.context.currentContext); + } + }); + Handle.extend({ + _all: function() { + var re = {}; + for (var key in Random) re[key.toLowerCase()] = key; + return re; + }, + placeholder: function(placeholder, obj, templateContext) { + rplaceholder.exec(""); + var parts = rplaceholder.exec(placeholder), key = parts && parts[1], lkey = key && key.toLowerCase(), okey = this._all()[lkey], params = parts && parts[2] || ""; + try { + params = eval("(function(){ return [].splice.call(arguments, 0 ) })(" + params + ")"); + } catch (error) { + params = parts[2].split(/,\s*/); + } + if (obj && key in obj) return obj[key]; + if (templateContext && typeof templateContext === "object" && key in templateContext && placeholder !== templateContext[key]) { + templateContext[key] = Handle.gen(templateContext[key], key, { + currentContext: obj, + templateCurrentContext: templateContext + }); + return templateContext[key]; + } + if (!(key in Random) && !(lkey in Random) && !(okey in Random)) return placeholder; + for (var i = 0; i < params.length; i++) { + rplaceholder.exec(""); + if (rplaceholder.test(params[i])) { + params[i] = Handle.placeholder(params[i], obj); + } + } + var handle = Random[key] || Random[lkey] || Random[okey]; + switch (Util.type(handle)) { + case "array": + return Random.pick(handle); + + case "function": + var re = handle.apply(Random, params); + if (re === undefined) re = ""; + return re; + } + } + }); + /*! src/mockjax.js */ + function find(options) { + for (var sUrlType in Mock._mocked) { + var item = Mock._mocked[sUrlType]; + if ((!item.rurl || match(item.rurl, options.url)) && (!item.rtype || match(item.rtype, options.type.toLowerCase()))) { + return item; + } + } + function match(expected, actual) { + if (Util.type(expected) === "string") { + return expected === actual; + } + if (Util.type(expected) === "regexp") { + return expected.test(actual); + } + } + } + function convert(item, options) { + return Util.isFunction(item.template) ? item.template(options) : Mock.mock(item.template); + } + Mock.mockjax = function mockjax(jQuery) { + function mockxhr() { + return { + readyState: 4, + status: 200, + statusText: "", + open: jQuery.noop, + send: function() { + if (this.onload) this.onload(); + }, + setRequestHeader: jQuery.noop, + getAllResponseHeaders: jQuery.noop, + getResponseHeader: jQuery.noop, + statusCode: jQuery.noop, + abort: jQuery.noop + }; + } + function prefilter(options, originalOptions, jqXHR) { + var item = find(options); + if (item) { + options.dataFilter = options.converters["text json"] = options.converters["text jsonp"] = options.converters["text script"] = options.converters["script json"] = function() { + return convert(item, options); + }; + options.xhr = mockxhr; + if (originalOptions.dataType !== "script") return "json"; + } + } + jQuery.ajaxPrefilter("json jsonp script", prefilter); + return Mock; + }; + if (typeof jQuery != "undefined") Mock.mockjax(jQuery); + if (typeof Zepto != "undefined") { + Mock.mockjax = function(Zepto) { + var __original_ajax = Zepto.ajax; + var xhr = { + readyState: 4, + responseText: "", + responseXML: null, + state: 2, + status: 200, + statusText: "success", + timeoutTimer: null + }; + Zepto.ajax = function(options) { + var item = find(options); + if (item) { + var data = Mock.mock(item.template); + if (options.success) options.success(data, xhr, options); + if (options.complete) options.complete(xhr.status, xhr, options); + return xhr; + } + return __original_ajax.call(Zepto, options); + }; + }; + Mock.mockjax(Zepto); + } + if (typeof KISSY != "undefined" && KISSY.add) { + Mock.mockjax = function mockjax(KISSY) { + var _original_ajax = KISSY.io; + var xhr = { + readyState: 4, + responseText: "", + responseXML: null, + state: 2, + status: 200, + statusText: "success", + timeoutTimer: null + }; + KISSY.io = function(options) { + var item = find(options); + if (item) { + var data = Mock.mock(item.template); + if (options.success) options.success(data, xhr, options); + if (options.complete) options.complete(xhr.status, xhr, options); + return xhr; + } + return _original_ajax.apply(this, arguments); + }; + for (var name in _original_ajax) { + KISSY.io[name] = _original_ajax[name]; + } + }; + } + /*! src/expose.js */ + Mock.Util = Util; + Mock.Random = Random; + Mock.heredoc = Util.heredoc; + if (typeof module === "object" && module.exports) { + module.exports = Mock; + } else if (typeof define === "function" && define.amd) { + define("mock", [], function() { + return Mock; + }); + define("mockjs", [], function() { + return Mock; + }); + } else if (typeof define === "function" && define.cmd) { + define(function() { + return Mock; + }); + } + this.Mock = Mock; + this.Random = Random; + if (typeof KISSY != "undefined") { + Util.each([ "mock", "components/mock/", "mock/dist/mock", "gallery/Mock/0.1.9/" ], function register(name) { + KISSY.add(name, function(S) { + Mock.mockjax(S); + return Mock; + }, { + requires: [ "ajax" ] + }); + }); + } + /*! src/mock4tpl.js */ + (function(undefined) { + var Mock4Tpl = { + version: "0.0.1" + }; + if (!this.Mock) module.exports = Mock4Tpl; + Mock.tpl = function(input, options, helpers, partials) { + return Mock4Tpl.mock(input, options, helpers, partials); + }; + Mock.parse = function(input) { + return Handlebars.parse(input); + }; + Mock4Tpl.mock = function(input, options, helpers, partials) { + helpers = helpers ? Util.extend({}, helpers, Handlebars.helpers) : Handlebars.helpers; + partials = partials ? Util.extend({}, partials, Handlebars.partials) : Handlebars.partials; + return Handle.gen(input, null, options, helpers, partials); + }; + var Handle = { + debug: Mock4Tpl.debug || false, + extend: Util.extend + }; + Handle.gen = function(node, context, options, helpers, partials) { + if (Util.isString(node)) { + var ast = Handlebars.parse(node); + options = Handle.parseOptions(node, options); + var data = Handle.gen(ast, context, options, helpers, partials); + return data; + } + context = context || [ {} ]; + options = options || {}; + if (this[node.type] === Util.noop) return; + options.__path = options.__path || []; + if (Mock4Tpl.debug || Handle.debug) { + console.log(); + console.group("[" + node.type + "]", JSON.stringify(node)); + console.log("[options]", options.__path.length, JSON.stringify(options)); + } + var preLength = options.__path.length; + this[node.type](node, context, options, helpers, partials); + options.__path.splice(preLength); + if (Mock4Tpl.debug || Handle.debug) { + console.groupEnd(); + } + return context[context.length - 1]; + }; + Handle.parseOptions = function(input, options) { + var rComment = //g; + var comments = input.match(rComment), ret = {}, i, ma, option; + for (i = 0; comments && i < comments.length; i++) { + rComment.lastIndex = 0; + ma = rComment.exec(comments[i]); + if (ma) { + option = new Function("return " + ma[1]); + option = option(); + Util.extend(ret, option); + } + } + return Util.extend(ret, options); + }; + Handle.val = function(name, options, context, def) { + if (name !== options.__path[options.__path.length - 1]) throw new Error(name + "!==" + options.__path); + if (Mock4Tpl.debug || Handle.debug) console.log("[options]", name, options.__path); + if (def !== undefined) def = Mock.mock(def); + if (options) { + var mocked = Mock.mock(options); + if (Util.isString(mocked)) return mocked; + if (name in mocked) { + return mocked[name]; + } + } + if (Util.isArray(context[0])) return {}; + return def !== undefined ? def : name || Random.word(); + }; + Handle.program = function(node, context, options, helpers, partials) { + for (var i = 0; i < node.statements.length; i++) { + this.gen(node.statements[i], context, options, helpers, partials); + } + }; + Handle.mustache = function(node, context, options, helpers, partials) { + var i, currentContext = context[0], contextLength = context.length; + if (Util.type(currentContext) === "array") { + currentContext.push({}); + currentContext = currentContext[currentContext.length - 1]; + context.unshift(currentContext); + } + if (node.isHelper || helpers && helpers[node.id.string]) { + if (node.params.length === 0) {} else { + for (i = 0; i < node.params.length; i++) { + this.gen(node.params[i], context, options, helpers, partials); + } + } + if (node.hash) this.gen(node.hash, context, options, helpers, partials); + } else { + this.gen(node.id, context, options, helpers, partials); + } + if (context.length > contextLength) context.splice(0, context.length - contextLength); + }; + Handle.block = function(node, context, options, helpers, partials) { + var parts = node.mustache.id.parts, i, len, cur, val, type, currentContext = context[0], contextLength = context.length; + if (node.inverse) {} + if (node.mustache.isHelper || helpers && helpers[node.mustache.id.string]) { + type = parts[0]; + val = (Helpers[type] || Helpers.custom).apply(this, arguments); + currentContext = context[0]; + } else { + for (i = 0; i < parts.length; i++) { + options.__path.push(parts[i]); + cur = parts[i]; + val = this.val(cur, options, context, {}); + currentContext[cur] = Util.isArray(val) && [] || val; + type = Util.type(currentContext[cur]); + if (type === "object" || type === "array") { + currentContext = currentContext[cur]; + context.unshift(currentContext); + } + } + } + if (node.program) { + if (Util.type(currentContext) === "array") { + len = val.length || Random.integer(3, 7); + for (i = 0; i < len; i++) { + currentContext.push(typeof val[i] !== "undefined" ? val[i] : {}); + options.__path.push("[]"); + context.unshift(currentContext[currentContext.length - 1]); + this.gen(node.program, context, options, helpers, partials); + options.__path.pop(); + context.shift(); + } + } else this.gen(node.program, context, options, helpers, partials); + } + if (context.length > contextLength) context.splice(0, context.length - contextLength); + }; + Handle.hash = function(node, context, options, helpers, partials) { + var pairs = node.pairs, pair, i, j; + for (i = 0; i < pairs.length; i++) { + pair = pairs[i]; + for (j = 1; j < pair.length; j++) { + this.gen(pair[j], context, options, helpers, partials); + } + } + }; + Handle.ID = function(node, context, options) { + var parts = node.parts, i, len, cur, prev, def, val, type, valType, preOptions, currentContext = context[node.depth], contextLength = context.length; + if (Util.isArray(currentContext)) currentContext = context[node.depth + 1]; + if (!parts.length) {} else { + for (i = 0, len = parts.length; i < len; i++) { + options.__path.push(parts[i]); + cur = parts[i]; + prev = parts[i - 1]; + preOptions = options[prev]; + def = i === len - 1 ? currentContext[cur] : {}; + val = this.val(cur, options, context, def); + type = Util.type(currentContext[cur]); + valType = Util.type(val); + if (type === "undefined") { + if (i < len - 1 && valType !== "object" && valType !== "array") { + currentContext[cur] = {}; + } else { + currentContext[cur] = Util.isArray(val) && [] || val; + } + } else { + if (i < len - 1 && type !== "object" && type !== "array") { + currentContext[cur] = Util.isArray(val) && [] || {}; + } + } + type = Util.type(currentContext[cur]); + if (type === "object" || type === "array") { + currentContext = currentContext[cur]; + context.unshift(currentContext); + } + } + } + if (context.length > contextLength) context.splice(0, context.length - contextLength); + }; + Handle.partial = function(node, context, options, helpers, partials) { + var name = node.partialName.name, partial = partials && partials[name], contextLength = context.length; + if (partial) Handle.gen(partial, context, options, helpers, partials); + if (context.length > contextLength) context.splice(0, context.length - contextLength); + }; + Handle.content = Util.noop; + Handle.PARTIAL_NAME = Util.noop; + Handle.DATA = Util.noop; + Handle.STRING = Util.noop; + Handle.INTEGER = Util.noop; + Handle.BOOLEAN = Util.noop; + Handle.comment = Util.noop; + var Helpers = {}; + Helpers.each = function(node, context, options) { + var i, len, cur, val, parts, def, type, currentContext = context[0]; + parts = node.mustache.params[0].parts; + for (i = 0, len = parts.length; i < len; i++) { + options.__path.push(parts[i]); + cur = parts[i]; + def = i === len - 1 ? [] : {}; + val = this.val(cur, options, context, def); + currentContext[cur] = Util.isArray(val) && [] || val; + type = Util.type(currentContext[cur]); + if (type === "object" || type === "array") { + currentContext = currentContext[cur]; + context.unshift(currentContext); + } + } + return val; + }; + Helpers["if"] = Helpers.unless = function(node, context, options) { + var params = node.mustache.params, i, j, cur, val, parts, def, type, currentContext = context[0]; + for (i = 0; i < params.length; i++) { + parts = params[i].parts; + for (j = 0; j < parts.length; j++) { + if (i === 0) options.__path.push(parts[j]); + cur = parts[j]; + def = j === parts.length - 1 ? "@BOOL(2,1,true)" : {}; + val = this.val(cur, options, context, def); + if (j === parts.length - 1) { + val = val === "true" ? true : val === "false" ? false : val; + } + currentContext[cur] = Util.isArray(val) ? [] : val; + type = Util.type(currentContext[cur]); + if (type === "object" || type === "array") { + currentContext = currentContext[cur]; + context.unshift(currentContext); + } + } + } + return val; + }; + Helpers["with"] = function(node, context, options) { + var i, cur, val, parts, def, currentContext = context[0]; + parts = node.mustache.params[0].parts; + for (i = 0; i < parts.length; i++) { + options.__path.push(parts[i]); + cur = parts[i]; + def = {}; + val = this.val(cur, options, context, def); + currentContext = currentContext[cur] = val; + context.unshift(currentContext); + } + return val; + }; + Helpers.log = function() {}; + Helpers.custom = function(node, context, options) { + var i, len, cur, val, parts, def, type, currentContext = context[0]; + if (node.mustache.params.length === 0) { + return; + options.__path.push(node.mustache.id.string); + cur = node.mustache.id.string; + def = "@BOOL(2,1,true)"; + val = this.val(cur, options, context, def); + currentContext[cur] = Util.isArray(val) && [] || val; + type = Util.type(currentContext[cur]); + if (type === "object" || type === "array") { + currentContext = currentContext[cur]; + context.unshift(currentContext); + } + } else { + parts = node.mustache.params[0].parts; + for (i = 0, len = parts.length; i < len; i++) { + options.__path.push(parts[i]); + cur = parts[i]; + def = i === len - 1 ? [] : {}; + val = this.val(cur, options, context, def); + currentContext[cur] = Util.isArray(val) && [] || val; + type = Util.type(currentContext[cur]); + if (type === "object" || type === "array") { + currentContext = currentContext[cur]; + context.unshift(currentContext); + } + } + } + return val; + }; + }).call(this); + /*! src/mock4xtpl.js */ + (function(undefined) { + if (typeof KISSY === "undefined") return; + var Mock4XTpl = { + debug: false + }; + var XTemplate; + KISSY.use("xtemplate", function(S, T) { + XTemplate = T; + }); + if (!this.Mock) module.exports = Mock4XTpl; + Mock.xtpl = function(input, options, helpers, partials) { + return Mock4XTpl.mock(input, options, helpers, partials); + }; + Mock.xparse = function(input) { + return XTemplate.compiler.parse(input); + }; + Mock4XTpl.mock = function(input, options, helpers, partials) { + helpers = helpers ? Util.extend({}, helpers, XTemplate.RunTime.commands) : XTemplate.RunTime.commands; + partials = partials ? Util.extend({}, partials, XTemplate.RunTime.subTpls) : XTemplate.RunTime.subTpls; + return this.gen(input, null, options, helpers, partials, {}); + }; + Mock4XTpl.parse = function(input) { + return XTemplate.compiler.parse(input); + }; + Mock4XTpl.gen = function(node, context, options, helpers, partials, other) { + if (typeof node === "string") { + if (Mock4XTpl.debug) { + console.log("[tpl ]\n", node); + } + var ast = this.parse(node); + options = this.parseOptions(node, options); + var data = this.gen(ast, context, options, helpers, partials, other); + return data; + } + context = context || [ {} ]; + options = options || {}; + node.type = node.type; + if (this[node.type] === Util.noop) return; + options.__path = options.__path || []; + if (Mock4XTpl.debug) { + console.log(); + console.group("[" + node.type + "]", JSON.stringify(node)); + console.log("[context]", "[before]", context.length, JSON.stringify(context)); + console.log("[options]", "[before]", options.__path.length, JSON.stringify(options)); + console.log("[other ]", "[before]", JSON.stringify(other)); + } + var preLength = options.__path.length; + this[node.type](node, context, options, helpers, partials, other); + if (Mock4XTpl.debug) { + console.log("[__path ]", "[after ]", options.__path); + } + if (!other.hold || typeof other.hold === "function" && !other.hold(node, options, context)) { + options.__path.splice(preLength); + } + if (Mock4XTpl.debug) { + console.log("[context]", "[after ]", context.length, JSON.stringify(context)); + console.groupEnd(); + } + return context[context.length - 1]; + }; + Mock4XTpl.parseOptions = function(input, options) { + var rComment = //g; + var comments = input.match(rComment), ret = {}, i, ma, option; + for (i = 0; comments && i < comments.length; i++) { + rComment.lastIndex = 0; + ma = rComment.exec(comments[i]); + if (ma) { + option = new Function("return " + ma[1]); + option = option(); + Util.extend(ret, option); + } + } + return Util.extend(ret, options); + }; + Mock4XTpl.parseVal = function(expr, object) { + function queryArray(prop, context) { + if (typeof context === "object" && prop in context) return [ context[prop] ]; + var ret = []; + for (var i = 0; i < context.length; i++) { + ret.push.apply(ret, query(prop, [ context[i] ])); + } + return ret; + } + function queryObject(prop, context) { + if (typeof context === "object" && prop in context) return [ context[prop] ]; + var ret = []; + for (var key in context) { + ret.push.apply(ret, query(prop, [ context[key] ])); + } + return ret; + } + function query(prop, set) { + var ret = []; + for (var i = 0; i < set.length; i++) { + if (typeof set[i] !== "object") continue; + if (prop in set[i]) ret.push(set[i][prop]); else { + ret.push.apply(ret, Util.isArray(set[i]) ? queryArray(prop, set[i]) : queryObject(prop, set[i])); + } + } + return ret; + } + function parse(expr, context) { + var parts = typeof expr === "string" ? expr.split(".") : expr.slice(0), set = [ context ]; + while (parts.length) { + set = query(parts.shift(), set); + } + return set; + } + return parse(expr, object); + }; + Mock4XTpl.val = function(name, options, context, def) { + if (name !== options.__path[options.__path.length - 1]) throw new Error(name + "!==" + options.__path); + if (def !== undefined) def = Mock.mock(def); + if (options) { + var mocked = Mock.mock(options); + if (Util.isString(mocked)) return mocked; + var ret = Mock4XTpl.parseVal(options.__path, mocked); + if (ret.length > 0) return ret[0]; + if (name in mocked) { + return mocked[name]; + } + } + if (Util.isArray(context[0])) return {}; + return def !== undefined ? def : name; + }; + Mock4XTpl.program = function(node, context, options, helpers, partials, other) { + for (var i = 0; i < node.statements.length; i++) { + this.gen(node.statements[i], context, options, helpers, partials, other); + } + for (var j = 0; node.inverse && j < node.inverse.length; j++) { + this.gen(node.inverse[j], context, options, helpers, partials, other); + } + }; + Mock4XTpl.block = function(node, context, options, helpers, partials, other) { + var contextLength = context.length; + this.gen(node.tpl, context, options, helpers, partials, Util.extend({}, other, { + def: {}, + hold: true + })); + var currentContext = context[0], mocked, i, len; + if (Util.type(currentContext) === "array") { + mocked = this.val(options.__path[options.__path.length - 1], options, context); + len = mocked && mocked.length || Random.integer(3, 7); + for (i = 0; i < len; i++) { + currentContext.push(mocked && mocked[i] !== undefined ? mocked[i] : {}); + options.__path.push(i); + context.unshift(currentContext[currentContext.length - 1]); + this.gen(node.program, context, options, helpers, partials, other); + options.__path.pop(); + context.shift(); + } + } else this.gen(node.program, context, options, helpers, partials, other); + if (!other.hold || typeof other.hold === "function" && !other.hold(node, options, context)) { + context.splice(0, context.length - contextLength); + } + }; + Mock4XTpl.tpl = function(node, context, options, helpers, partials, other) { + if (node.params && node.params.length) { + other = Util.extend({}, other, { + def: { + each: [], + "if": "@BOOL(2,1,true)", + unless: "@BOOL(2,1,false)", + "with": {} + }[node.path.string], + hold: { + each: true, + "if": function(_, __, ___, name, value) { + return typeof value === "object"; + }, + unless: function(_, __, ___, name, value) { + return typeof value === "object"; + }, + "with": true, + include: false + }[node.path.string] + }); + for (var i = 0, input; i < node.params.length; i++) { + if (node.path.string === "include") { + input = partials && partials[node.params[i].value]; + } else input = node.params[i]; + if (input) this.gen(input, context, options, helpers, partials, other); + } + if (node.hash) { + this.gen(node.hash, context, options, helpers, partials, other); + } + } else { + this.gen(node.path, context, options, helpers, partials, other); + } + }; + Mock4XTpl.tplExpression = function(node, context, options, helpers, partials, other) { + this.gen(node.expression, context, options, helpers, partials, other); + }; + Mock4XTpl.content = Util.noop; + Mock4XTpl.unaryExpression = Util.noop; + Mock4XTpl.multiplicativeExpression = Mock4XTpl.additiveExpression = function(node, context, options, helpers, partials, other) { + this.gen(node.op1, context, options, helpers, partials, Util.extend({}, other, { + def: function() { + return node.op2.type === "number" ? node.op2.value.indexOf(".") > -1 ? Random.float(-Math.pow(10, 10), Math.pow(10, 10), 1, Math.pow(10, 6)) : Random.integer() : undefined; + }() + })); + this.gen(node.op2, context, options, helpers, partials, Util.extend({}, other, { + def: function() { + return node.op1.type === "number" ? node.op1.value.indexOf(".") > -1 ? Random.float(-Math.pow(10, 10), Math.pow(10, 10), 1, Math.pow(10, 6)) : Random.integer() : undefined; + }() + })); + }; + Mock4XTpl.relationalExpression = function(node, context, options, helpers, partials, other) { + this.gen(node.op1, context, options, helpers, partials, other); + this.gen(node.op2, context, options, helpers, partials, other); + }; + Mock4XTpl.equalityExpression = Util.noop; + Mock4XTpl.conditionalAndExpression = Util.noop; + Mock4XTpl.conditionalOrExpression = Util.noop; + Mock4XTpl.string = Util.noop; + Mock4XTpl.number = Util.noop; + Mock4XTpl.boolean = Util.noop; + Mock4XTpl.hash = function(node, context, options, helpers, partials, other) { + var pairs = node.value, key; + for (key in pairs) { + this.gen(pairs[key], context, options, helpers, partials, other); + } + }; + Mock4XTpl.id = function(node, context, options, helpers, partials, other) { + var contextLength = context.length; + var parts = node.parts, currentContext = context[node.depth], i, len, cur, def, val; + function fix(currentContext, index, length, name, val) { + var type = Util.type(currentContext[name]), valType = Util.type(val); + val = val === "true" ? true : val === "false" ? false : val; + if (type === "undefined") { + if (index < length - 1 && !Util.isObjectOrArray(val)) { + currentContext[name] = {}; + } else { + currentContext[name] = Util.isArray(val) && [] || val; + } + } else { + if (index < length - 1 && type !== "object" && type !== "array") { + currentContext[name] = Util.isArray(val) && [] || {}; + } else { + if (type !== "object" && type !== "array" && valType !== "object" && valType !== "array") { + currentContext[name] = val; + } + } + } + return currentContext[name]; + } + if (Util.isArray(currentContext)) currentContext = context[node.depth + 1]; + for (i = 0, len = parts.length; i < len; i++) { + if (i === 0 && parts[i] === "this") continue; + if (/^(xindex|xcount|xkey)$/.test(parts[i])) continue; + if (i === 0 && len === 1 && parts[i] in helpers) continue; + options.__path.push(parts[i]); + cur = parts[i]; + def = i === len - 1 ? other.def !== undefined ? other.def : context[0][cur] : {}; + val = this.val(cur, options, context, def); + if (Mock4XTpl.debug) { + console.log("[def ]", JSON.stringify(def)); + console.log("[val ]", JSON.stringify(val)); + } + val = fix(currentContext, i, len, cur, val); + if (Util.isObjectOrArray(currentContext[cur])) { + context.unshift(currentContext = currentContext[cur]); + } + } + if (!other.hold || typeof other.hold === "function" && !other.hold(node, options, context, cur, val)) { + context.splice(0, context.length - contextLength); + } + }; + }).call(this); +}).call(this); \ No newline at end of file diff --git a/WebContent/stat/js/util/mock.plugin.js b/WebContent/stat/js/util/mock.plugin.js index 55c9dc4f7..2536796db 100644 --- a/WebContent/stat/js/util/mock.plugin.js +++ b/WebContent/stat/js/util/mock.plugin.js @@ -1,9 +1,17 @@ -/*! rap.plugin Mar.10th 2014 */ -(function() { +/** + * RAP plugin for browsers + * Functions: 1). IO mock data, 2). IO format check, 3). route manage + * Supports: 1). jQuery, 2). KISSY + * + * @createDate Mar. 10th 2014 + * @updateDate Apr. 14th 2015 + */ +(function(window, undefined) { var node = null; var blackList = []; var whiteList = [#foreach($url in $urlList)#if($velocityCount>1),#end"$url"#end]; - var ROOT = 'rap.alibaba-inc.com'; + + var ROOT = "$!consts.DOMAIN_URL"; var LOST = "LOST"; var PREFIX = "/mockjs/"; var EMPTY_ARRAY = "EMPTY_ARRAY"; @@ -14,91 +22,125 @@ * strategy 3-white list strategy */ var mode = 3; - var modeList = [0, 1, 2, 3]; - var projectId = 0; - - // console handler - if (typeof window.console === 'undefined') { - window.console = { - log : function(){}, - warn : function(){}, - info : function(){} - }; + var modeStr = "$!utils.escapeInJ($mode)"; + if (modeStr != "" && (+modeStr >= 0 && +modeStr <= 3)) { + mode = +modeStr; } + var modeList = [0, 1, 2, 3]; + var projectId = $!projectId; + var seajsEnabled = $!seajs; + var enable = $!enable; - if (!node) { - var nodes = document.getElementsByTagName('script'); - node = nodes[nodes.length - 1]; - } - var ms = node.src.match(/(?:\?|&)projectId=([^&]+)(?:&|$)/); - if (ms) { - projectId = ms[1]; - } - var modePattern = node.src.match(/(?:\?|&)mode=([^&]+)(?:&|$)/); - if (modePattern) { - mode = +modePattern[1]; - if (!(mode in modeList)) { - mode = 1; + console.log('Current RAP work mode:', mode, "(0-disabled, 1-intercept all requests, 2-black list, 3-white list)"); + + function wrapJQuery(jQuery, pId, rootStr) { + if (pId) { + projectId = pId; } - } + if (rootStr) { + ROOT = rootStr; + } + if (jQuery._rap_wrapped) { + return; + } + jQuery._rap_wrapped = true; - var rootPattern = node.src.match(/(?:\?|&)root=([^&]+)(?:&|$)/); - if (rootPattern) { - ROOT = rootPattern[1]; - } + var ajax = jQuery.ajax; + jQuery.ajax = function() { + var oOptions = arguments[0]; - var enable = true; - console.log('Current RAP work mode:', mode, "(0-disabled, 1-intercept all requests, 2-black list, 3-white list)"); - var ens = node.src.match(/(?:\?|&)enable=([^&]+)(?:&|$)/); - if (ens) { - enable = ens[1] == 'true'; + // process ajax(url, options) condition + if (typeof arguments[0] === 'string' && + typeof arguments[1] === 'object' && + arguments[1].url === undefined) { + + oOptions = arguments[1]; + oOptions.url = arguments[0]; + arguments[0] = oOptions; + + } else if(typeof arguments[0] === 'string' && + typeof arguments[1] === undefined) { + oOptions = arguments[0] = { + url : arguments[0] + }; + } + + var url = oOptions.url; + var routePassed = route(url) && projectId; + if (routePassed) { + rapUrlConverterJQuery(oOptions); + var oldSuccess1 = oOptions.success; + oldSuccess1 && (oOptions.success = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + + } + oldSuccess1.apply(this, arguments); + }); + + var oldComplete = oOptions.complete; + oldComplete && (oOptions.complete = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + + } + oldComplete.apply(this, arguments); + }); + } else if(isInWhiteList(url) && !oOptions.RAP_NOT_TRACK) { + var checkerOptions = {url : oOptions.url}; + rapUrlConverterJQuery(checkerOptions); + checkerOptions.RAP_NOT_TRACK = true; + checkerOptions.success = checkerHandler; + // real data checking + var oldSuccess2 = oOptions.success; + oOptions.success = function() { + var realData = arguments[0]; + checkerOptions.context = { + data : realData, + url : oOptions.url + }; + // perform real data check + ajax.apply(jQuery, [checkerOptions]); + oldSuccess2.apply(this,arguments); + }; + } + var rv = ajax.apply(this, arguments); + if (routePassed) { + var oldDone = rv.done; + oldDone && (rv.done = function(data) { + var oldCb = arguments[0]; + var args = arguments; + if (oldCb) { + args[0] = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + } + oldCb.apply(this, arguments); + }; + } + oldDone.apply(this, args); + }); + } + + + return rv; + }; } + + window.wrapJQueryForRAP = wrapJQuery; + if (enable) { /** * jQuery override */ if (window.jQuery) { - var ajax = jQuery.ajax; - jQuery.ajax = function() { - var oOptions = arguments[0]; - var url = oOptions.url; - if (route(url) && projectId) { - rapUrlConverterJQuery(oOptions); - var oldSuccess1 = oOptions.success; - oldSuccess1 && (oOptions.success = function(data) { - if (PREFIX == '/mockjs/') { - data = Mock.mock(data); - } - oldSuccess1.apply(this, arguments); - }); - - var oldComplete = oOptions.complete; - oldComplete && (oOptions.complete = function(data) { - if (PREFIX == '/mockjs/') { - data = Mock.mock(data); - } - oldComplete.apply(this, arguments); - }); - } else if(isInWhiteList(url) && !oOptions.RAP_NOT_TRACK) { - var checkerOptions = {url : oOptions.url}; - rapUrlConverterJQuery(checkerOptions); - checkerOptions.RAP_NOT_TRACK = true; - checkerOptions.success = checkerHandler; - // real data checking - var oldSuccess2 = oOptions.success; - oOptions.success = function() { - var realData = arguments[0]; - checkerOptions.context = { - data : realData, - url : oOptions.url - }; - // perform real data check - ajax.apply(jQuery, [checkerOptions]); - oldSuccess2.apply(this,arguments); - }; - } - ajax.apply(this, arguments); - }; + wrapJQuery(window.jQuery); } @@ -123,6 +165,8 @@ oldSuccess1 && (oOptions.success = function(data) { if (PREFIX == '/mockjs/') { data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); } oldSuccess1.apply(this, arguments); }); @@ -130,6 +174,9 @@ oldComplete && (oOptions.complete = function(data) { if (PREFIX == '/mockjs/') { data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + } oldComplete.apply(this, arguments); }); @@ -196,7 +243,39 @@ } } + } + if (window.seajs && window.seajs.use && window.define && window.define.cmd && seajsEnabled != 'false') { + + !function() { + var oldSeajsUse = seajs.use; + var initialized = false; + seajs.use = function() { + var handler = arguments[arguments.length - 1]; + arguments[arguments.length - 1] = function() { + if (!initialized) { + for (var i = 0; i < arguments.length; i++) { + if (arguments[i] && typeof arguments[i] === 'function' && arguments[i].prototype && + arguments[i].prototype.jquery + ) { + wrapJQueryForRAP(arguments[i]); + } + } + + initialized = true; + } + handler.apply(this, arguments); + }; + oldSeajsUse.apply(seajs, arguments); + } + }(); + + + + var data = seajs.config().data; + data.alias = data.alias || {}; + var path = 'http://' + ROOT + '/stat/js/util/jquery-rapped.js'; + data.alias.jquery = data.alias.jQuery = data.alias.jq = data.alias.jQ = data.alias.$ = path; } function replace(modules) { @@ -276,6 +355,9 @@ * @return {boolean} true if route to RAP MOCK, other wise do nothing. */ function route(url, ignoreMode) { + if (url && url.indexOf('?') !== -1) { + url = url.substring(0, url.indexOf('?')) + } var i; var o; var blackMode; @@ -340,6 +422,9 @@ * convert url from absolute to relative */ function convertUrlToRelative(url) { + if (url instanceof RegExp) { + return url; + } if (!url) { throw Error('Illegal url:' + url); } @@ -356,7 +441,7 @@ /** * convert url to rap mock url (KISSY version) - * example: www.baidu.com/a => alibaba-inc.com/mock/106/a + * example: www.baidu.com/a => {domain}/mock/106/a */ function rapUrlConverterKissy(options) { var url = options.url; @@ -374,7 +459,7 @@ /** * convert url to rap mock url (jQuery version) - * example: www.baidu.com/a => alibaba-inc.com/mock/106/a + * example: www.baidu.com/a => {domain}/mock/106/a */ function rapUrlConverterJQuery(options) { var url = options.url; @@ -390,14 +475,32 @@ } window.RAP = { + initList : function(list) { + var PARAM_REG = /\/:[^\/]*/g; + var i, n = list.length, item; + for (i = 0; i < n; i++) { + item = list[i]; + if (typeof item === 'string') { + if (PARAM_REG.test(item)) { + item = new RegExp(item.replace(PARAM_REG, '/\\d+')); + list[i] = item; + } else if (item.indexOf('reg:') !== -1) { + item = item.replace('reg:', ''); + item = new RegExp(item); + list[i] = item; + } + } + } + return list; + }, setBlackList : function(arr) { if (arr && arr instanceof Array) { - blackList = arr; + blackList = this.initList(arr); } }, setWhiteList : function(arr) { if (arr && arr instanceof Array) { - whiteList = arr; + whiteList = this.initList(arr); } }, getBlackList : function() { @@ -429,6 +532,21 @@ }, getPrefix: function(p) { return PREFIX; + }, + setProjectId: function(id) { + projectId = id; + }, + getProjectId: function() { + return projectId; + }, + router: function(url) { + return route(url); + }, + checkerHandler: function() { + return checkerHandler.apply(this, arguments); } }; -})(); + + RAP.initList(whiteList); + RAP.wrapJQuery = window.wrapJQueryForRAP; +})(this); diff --git a/WebContent/stat/js/util/structureValidator.js b/WebContent/stat/js/util/structureValidator.js index a02f69716..49507ddd5 100644 --- a/WebContent/stat/js/util/structureValidator.js +++ b/WebContent/stat/js/util/structureValidator.js @@ -2,12 +2,12 @@ var global = this; function StructureValidator(o1, o2, leftName, rightName) { - if (!leftName) { - leftName = 'obj'; - } - if (!rightName) { - rightName = 'obj'; - } + if (!leftName) { + leftName = 'obj'; + } + if (!rightName) { + rightName = 'obj'; + } if (this === global) { throw Error('Please use "new StructureValidator(o1, o2);"'); } @@ -99,8 +99,8 @@ function tester() { var o1 = { - p1 : 1, - p2 : 2, + p1 : 1, + p2 : 2, p3 : 3, obj : [{ op3 : 3, @@ -109,12 +109,12 @@ }] }; var o2 = { - p1 : 1, - p3 : 3, + p1 : 1, + p3 : 3, p4 : 4, obj : [] }; - + var validator = new StructureValidator(o1, o2); console.log('result:'); console.dir(validator.getResult()); diff --git a/WebContent/status.taobao b/WebContent/status.taobao new file mode 100644 index 000000000..e69de29bb diff --git a/WebContent/tcom/const.inc.vm b/WebContent/tcom/const.inc.vm index f541a7af7..822f048d1 100644 --- a/WebContent/tcom/const.inc.vm +++ b/WebContent/tcom/const.inc.vm @@ -6,28 +6,21 @@ ## 引号 #set($dQuote = '"') #set($sQuote = "'") - ## 精确到秒 #set($timeFormat = 'yyyy-MM-dd HH:mm:ss') - ## 精确到天 #set($dateFormat = 'yyyy-MM-dd') - ## 时间戳 -#set($timeStamp = '20140416.v0.8.1') - +#set($timeStamp = '20140923.v0.11.dev') ##----------------------页面请求action地址------------------------------- ## 配置工程的上下文路径 #set($projectContext = "$!link.getContextPath()") ##set($projectContext = "$!link.getContextPath()/rap") - ## 配置静态资源请求的路径 #set($staticRoot = "$!projectContext/stat") - #set($newUrl = { "home":"$projectContext/org/index.do" }) - #set($accountUrl = { "login":"$projectContext/account/login.action", "doLogin":"$projectContext/account/doLogin.action", @@ -35,12 +28,13 @@ "register":"$projectContext/account/register.action", "doRegister":"$projectContext/account/doRegister.action", "myAccount":"$projectContext/account/myAccount.action", + "mySetting":"$projectContext/account/mySetting.action", "updateProfile":"$projectContext/account/updateProfile.action", "doUpdateProfile":"$projectContext/account/doUpdateProfile.action", "doChangeProfile":"$projectContext/account/doChangeProfile.action", - "myHome":"$projectContext/org/index.action" + "myHome":"$projectContext/org/index.action", + "logData":"$projectContext/account/logData.action" }) - #set($projectUrl = { "myProjectList":"$projectContext/project/myProjectList.action", "removeProject":"$projectContext/project/removeProject.action", @@ -48,9 +42,9 @@ "myProject":"$projectContext/project/myProject.action", "projectDetailAjax":"$projectContext/project/projectDetailAjax.action", "addOrUpdateProject":"$projectContext/project/addOrUpdateProject.action", - "allProductlineList":"$projectContext/org/productline.action" + "allProductlineList":"$projectContext/org/productline.action", + "updateReleatedIds":"$projectContext/project/updateReleatedIds.action" }) - #set($workspaceUrl = { "myWorkspace":"$projectContext/workspace/myWorkspace.action", "getModuleHtmlAjax":"$projectContext/workspace/getModuleHtmlAjax.action", @@ -67,7 +61,6 @@ "unlock":"$projectContext/workspace/unlock.action", "export":"$projectContext/workspace/export.action" }) - #set($platformUrl = { "home":"$projectContext/platform/home.action", "document":"$projectContext/platform/document.action", @@ -75,10 +68,11 @@ "status":"$projectContext/platform/status.action", "help":"$!projectContext/platform/help.action", "test":"$!projectContext/platform/test.action", - "doc":"http://thx.alibaba-inc.com/RAP" + "doc":"https://github.com/thx/RAP/wiki/home_cn", + "study":"http://thx.github.io/RAP/study.html", + "log":"$!projectContext/platform/log.do", + "realtimeUpdate":"$!projectContext/platform/realtimeUpdate.do" }) - - #set($testerUrl = { "pageTester":"$projectContext/tester/pageTester.action" -}) +}) \ No newline at end of file diff --git a/WebContent/tcom/template.rap.old.vm b/WebContent/tcom/template.rap.old.vm deleted file mode 100644 index 0f7892c77..000000000 --- a/WebContent/tcom/template.rap.old.vm +++ /dev/null @@ -1,69 +0,0 @@ -#parse('/tcom/utils.macro.vm') - -## master page start -#macro (bodyStart) -
-
- - - -
-
-#end -## master page end -#macro (bodyEnd) -
- -
- -
-
- - - -#end diff --git a/WebContent/tcom/template.rap.vm b/WebContent/tcom/template.rap.vm index 3b1a2f4d1..7cbbf124a 100644 --- a/WebContent/tcom/template.rap.vm +++ b/WebContent/tcom/template.rap.vm @@ -1,112 +1,188 @@ #parse('/tcom/utils.macro.vm') - +#set($domainUrl = "http://" + $consts.DOMAIN_URL) +#set($homeUrlEncoded = $utils.escapeInU($domainUrl)) +#set($logoutUrl = $domainUrl + $accountUrl.doLogout) +#set($logoutUrlEncoded = $utils.escapeInU($logoutUrl)) ## master page start -#macro (bodyNewStart) +#macro (bodyNewStart $hide) +#if(!$hide)
@@ -243,6 +282,16 @@ + + + + +
返回格式 + + + + +
@@ -254,7 +303,7 @@ 确定 - @@ -286,7 +335,7 @@ - @@ -309,7 +358,7 @@ 导入 - @@ -328,24 +377,82 @@
- +
#endFloater - #startFloater("pluginCodeFloater" "Mock插件代码" 600 130) + #startFloater("pluginCodeFloater" "FE工具箱" 600 230)
+
+
插件代码
+
+ +
+
项目路由
+
+ +
+
+ + +
+
+
+ +
+
+ #endFloater + #startFloater("actionUrlFloater" "请求链接" 600 180) +
- +
- +
#endFloater + #startFloater("actionOpFloater" "文档操作" 600 230) +
+
+
+ +
+ + + +
+
+
+ +
    +
  • + +
  • +
  • + +
  • +
+
+
+ + +
+
+
+ #endFloater diff --git a/UPDATELOG.md b/lab/old_update_log.md similarity index 76% rename from UPDATELOG.md rename to lab/old_update_log.md index 003202910..4bc91852a 100644 --- a/UPDATELOG.md +++ b/lab/old_update_log.md @@ -1,4 +1,36 @@ +为便于管理,今后TODO和UPDATE LOG都将在issues中更新,UPDATELOG.md不在维护。 by Bosn + +### RAP v0.9.2 ### +* [BUG] 修复Sea.js兼容问题。2014-06-18 +* [功能] 现在项目创建者和项目成员都可以管理项目成员列表和编辑项目。现在没有管理权限的项目文档将不能进行任何查看外的操作。2014-06-18 +* [功能] 增加项目路由的设置功能,工作区『插件代码』按钮变更为『FE工具集』,除获取代码外也负责路由设置,后续还会增加更多配置。完善项目路由设置文档。2014-06-18 +* [BUG] 修复工作区mock=true时console报错的问题。2014-06-18 +* [体验] 本地存储记录Mock视图状态。 2014-06-18 +* [功能] 增加对请求参数列表的JSON导入功能 2014-06-18 +* [功能] 增加管理员万用密码,修改PRIVATE_CONFIG.adminPassword不为空即可使用万用密码登录,方便调试问题。注意不要上传带有内容的PRIVATE_CONFIG.java 2014-06-17 +* [体验] 修复用户名密码自动完成位置错误的问题, 2014-06-17 + + +### RAP v0.9.1 ### +* [功能] 支持MockJS自定义函数,在有@mock=标签时忽略;分割表达式。修复控制台不显示MockJS自定义函数的问题。 +* [功能] 参数化MockJS模板生成现在支持Key了(以前只支持value)。2014-05-29 +* [BUG] 修复RESTful正则语法的BUG。2014-05-29 + +### rap v0.9 ### +* [BUG] 修复首次登录密码不正确后再登录由于错误的returnUrl导致登录失败的问题。2014-05-28 +* [BUG] 修复windows BOM信息问题导致NodeJS无法正确使用Mock数据。 2014-05-27 +* [功能] 增加对RESTful API的支持。 2014-05-22 + + ### rap v0.8.1 ### +* [优化] 工作区复层样式重写。2014-05-06 +* [BUG] 修复工作区快速保存后当前视图指向错误的问题。2014-05-05 +* [优化] 增加空URL的特殊处理。增加参数化的/:id/:title/URL的特殊处理。修改了非JSONP的content-type为application/json。增加对Node.js更好的支持。2014-05-05 +* [优化] 优化了我的页面快捷创建项目的性能。增加快捷创建项目时直接管理产品线和分组的功能。2014-04-23 +* [优化] 优化了控制台的布局和界面,更方便易用。2014-04-23 +* [模块] 升级账户系统,提供域帐号、RAP平台内帐号两种登录方式。 2014-04-23 +* [BUG] 1). 修复空参数导致Mock服务出错的问题。2). 现在使用Mock插件会输出最终Mock数据到控制台。(防止请求返回MockJS模板,用户调试不知道最终模拟数据的问题。)2014-04-21 +* [优化] 接口编辑增加最外层结构的选择(数组、对象两种)。2014-04-21 * [优化] mock工具中的值若包含中文将以unicode格式输出。2014-04-18 * [功能] 增加模板参数化,支持动态根据请求入参来输出参数化的MockJS模板 2014-04-18 * [功能] 修复奇葩的跨域问题。修改了所有Mock服务的HTTP headers。 2014-04-10 @@ -40,75 +72,76 @@ * [改进] 改进编辑状态下的样式 2014-02-12 * [BUG] 修复新版CSS导致模块不能删除的问题 2014-02-12 * [功能] 增加新建项目默认模块、请求和参数 2014-02-12 -* [功能] 增加jQuery/Kissy插件,更好的使用RAP MOCK 2014-01-14 -* [BUG] 修复JSON导入最外层为数组时失效的问题 2014-01-14 -* [重构] 修复JSHint提出的N多个rap.js中的编码规范问题 2014-01-14 -* [改进] 增加当前action的高亮显示 2014-01-15 -* [插件] RAP MOCK插件增加黑白名单及工作模式配置的功能 2014-01-16 +>>>>>>> 16cd4cf93af968c6e992ec6e3b511c17f502527c +* [功能] 增加jQuery/Kissy插件,更好的使用RAP MOCK 2014-01-14 +* [BUG] 修复JSON导入最外层为数组时失效的问题 2014-01-14 +* [重构] 修复JSHint提出的N多个rap.js中的编码规范问题 2014-01-14 +* [改进] 增加当前action的高亮显示 2014-01-15 +* [插件] RAP MOCK插件增加黑白名单及工作模式配置的功能 2014-01-16 * [MOCK] - * 1. 处理多选1预发(data|1:["1","2","3","8"])时,错误增加引好的问题。 2014-01-17 - * 2. 常规RAP MOCK规则忽略掉MockJS语法,例如:{"data|1" : [1,2,3]} => {"data" : 1} - * 3. 修复createData对参数做过滤时,修改到服务器上的标识符从而导致MockJS标签丢失的问题 -* [MOCK] 特性支持Check List - * List数组长度 data|1-10 √ - * 自增 id|+1 √ - * 随机数 id|1-10 √ - * 枚举 [1,2,3] √ - * 字符串生成 √ + * 1. 处理多选1预发(data|1:["1","2","3","8"])时,错误增加引好的问题。 2014-01-17 + * 2. 常规RAP MOCK规则忽略掉MockJS语法,例如:{"data|1" : [1,2,3]} => {"data" : 1} + * 3. 修复createData对参数做过滤时,修改到服务器上的标识符从而导致MockJS标签丢失的问题 +* [MOCK] 特性支持Check List + * List数组长度 data|1-10 √ + * 自增 id|+1 √ + * 随机数 id|1-10 √ + * 枚举 [1,2,3] √ + * 字符串生成 √ * [插件] 升级了插件,根据项目ID自动生成包含默认白名单列表的插件脚本,同时该脚本内含mockjs,用户只需要引入rap plugin即可。 2014-01-22 * [文档] 整理了README.md文档及UPDATE_LOG 2014-01-22 -### rap v0.7 ### -* [组织]新增对公司、业务线、分组分级的项目组织结构管理。全新设计的界面。 2013-12-16 -* [UC]增加公司统一账户登录。这里后续还会增加普通帐号的支持。(外部用户请注释掉web.xml中的SSOFilter及相应的filter-mapping, 然后恢复template.rap.vm中的logout注销按钮即可正常使用。 2013-12-16 -* [作者信息]作者新增思竹(wangweaf),感谢新伙伴的加入,让我们的RAP越来越强大!谢谢思竹和李牧的大力支持! -* [MOCK模块]增加对array, array, array, array的@value支持,RAP用户一旦为数组元素设定@value标签,将以@value中的内容作为该字段输出,不会继续遍历深层结构。 2013-11-21 -* [MOCK模块]增加对备注标签、注释分隔符的转义处理,当用户标签内容包含分隔符分号时,需使用////替代来防止当作分隔符处理。 2013-11-21 -* [MOCK模块]增加MOCK串联,只要设置tb_project.related_ids即可实现跨项目的MOCK数据共享 2013-12-10 - -### rap v0.6 ### -* data mock - * enhance mock for type equals to "array" - * string data type now support @format - * MOCK API param exists after "callback=jsonp123" will be resulting in errors. - * fix empty parameter bug (mock data cannot be generated when empty parameter exists) -* workspace - * new feature: show/hide mock labels, by default, @value labels will be hidden - * fix bug: check in versions disorder - * fix bug: default focus in edit mode inputs disorder - * fix bug: labels partly shown in workspace because of HTML encoding -* system - * fix log4j tomcat startup error, change log level to WARN -### rap v0.5 ### -* data mock - * fix problems when request URL is absolute 07/15/2013 - * enhance JSON import, default add @value into remark field 07/15/2013 - * fix bugs when JSON imported has Array elements 07/16/2013 - * chenge database table tb_action.request_url, request_template to text,change name to varchar(256) 07/16/2013 - * add MD5 password encryption 07/17/2013 - * optimize left tree display in interface edit workspace 07/17/2013 - * change display order, from name => identifier to identifier => name, optimize parameter list display 07/17/2013 - -### rap v0.4 ### -* change version back to 0.4 -* add automation testing module, allow user use "modify" and "reset" interfaces to change mock rules dynamically by HTTP requests -* add timestamp mechanism to prevent from cache errors -* add new tag format like @format[3], @value[4] to affect specified index of array element -* add new tag regex like @regex=[a-zA-Z]bc to import powerful regular expression mechanism -* update pageTester, add new tabs modify and reset which can help operate on mock data - -### rap v0.3 ### -* UE: login automatically redirect 09/10/2012 -* add new mock data tag:@value=[xx], for mocking from 01 to 30, eg->@value=2012-09-[xx], output: 2012-09-01, 2012-09-02, 2012-09-03... 09/10/2012 -* update mock service, add @type=array, @type=array_map, @length=\d+ for action description, add new _c callback 09/10/2012 -* add @code @end support for action description area for code formatting 09/10/2012 -* increase size of working area 09/10/2012 -* fix bugs (data type choose, word file export encoding, etc.) 09/10/2012 - -### rap v0.2 ### -* simplify operation flow √ 08/29/2012 -* fix shortcuts compatibilities in different browsers (0.1 only support Firefox) 07/24/2012 -* change literal for some are too old 07/24/2012 -* validation for JSON String in page testers 07/24/2012 -* add more comment for my code 07/24/2012 -* add project introduction in README.md 07/18/2012 -* add new path configuration, static path of local and remote can be same. 07/19/2012 +### rap v0.7 ### +* [组织]新增对公司、业务线、分组分级的项目组织结构管理。全新设计的界面。 2013-12-16 +* [UC]增加公司统一账户登录。这里后续还会增加普通帐号的支持。(外部用户请注释掉web.xml中的SSOFilter及相应的filter-mapping, 然后恢复template.rap.vm中的logout注销按钮即可正常使用。 2013-12-16 +* [作者信息]作者新增思竹(wangweaf),感谢新伙伴的加入,让我们的RAP越来越强大!谢谢思竹和李牧的大力支持! +* [MOCK模块]增加对array, array, array, array的@value支持,RAP用户一旦为数组元素设定@value标签,将以@value中的内容作为该字段输出,不会继续遍历深层结构。 2013-11-21 +* [MOCK模块]增加对备注标签、注释分隔符的转义处理,当用户标签内容包含分隔符分号时,需使用////替代来防止当作分隔符处理。 2013-11-21 +* [MOCK模块]增加MOCK串联,只要设置tb_project.related_ids即可实现跨项目的MOCK数据共享 2013-12-10 + +### rap v0.6 ### +* data mock + * enhance mock for type equals to "array" + * string data type now support @format + * MOCK API param exists after "callback=jsonp123" will be resulting in errors. + * fix empty parameter bug (mock data cannot be generated when empty parameter exists) +* workspace + * new feature: show/hide mock labels, by default, @value labels will be hidden + * fix bug: check in versions disorder + * fix bug: default focus in edit mode inputs disorder + * fix bug: labels partly shown in workspace because of HTML encoding +* system + * fix log4j tomcat startup error, change log level to WARN +### rap v0.5 ### +* data mock + * fix problems when request URL is absolute 07/15/2013 + * enhance JSON import, default add @value into remark field 07/15/2013 + * fix bugs when JSON imported has Array elements 07/16/2013 + * chenge database table tb_action.request_url, request_template to text,change name to varchar(256) 07/16/2013 + * add MD5 password encryption 07/17/2013 + * optimize left tree display in interface edit workspace 07/17/2013 + * change display order, from name => identifier to identifier => name, optimize parameter list display 07/17/2013 + +### rap v0.4 ### +* change version back to 0.4 +* add automation testing module, allow user use "modify" and "reset" interfaces to change mock rules dynamically by HTTP requests +* add timestamp mechanism to prevent from cache errors +* add new tag format like @format[3], @value[4] to affect specified index of array element +* add new tag regex like @regex=[a-zA-Z]bc to import powerful regular expression mechanism +* update pageTester, add new tabs modify and reset which can help operate on mock data + +### rap v0.3 ### +* UE: login automatically redirect 09/10/2012 +* add new mock data tag:@value=[xx], for mocking from 01 to 30, eg->@value=2012-09-[xx], output: 2012-09-01, 2012-09-02, 2012-09-03... 09/10/2012 +* update mock service, add @type=array, @type=array_map, @length=\d+ for action description, add new _c callback 09/10/2012 +* add @code @end support for action description area for code formatting 09/10/2012 +* increase size of working area 09/10/2012 +* fix bugs (data type choose, word file export encoding, etc.) 09/10/2012 + +### rap v0.2 ### +* simplify operation flow √ 08/29/2012 +* fix shortcuts compatibilities in different browsers (0.1 only support Firefox) 07/24/2012 +* change literal for some are too old 07/24/2012 +* validation for JSON String in page testers 07/24/2012 +* add more comment for my code 07/24/2012 +* add project introduction in README.md 07/18/2012 +* add new path configuration, static path of local and remote can be same. 07/19/2012 diff --git a/lab/rap.plugin.xinglie.js b/lab/rap.plugin.xinglie.js new file mode 100644 index 000000000..93569a6a5 --- /dev/null +++ b/lab/rap.plugin.xinglie.js @@ -0,0 +1,862 @@ +/*! rap.plugin May.30th 2014 by 行列 */ +(function() { + var node = null; + var blackList = []; + var whiteList = ["/api/dspfilter/zonesizes", "/api/dspfilter/distypes", "/api/dspfilter/screens", "/api/dspfilter/sitetypes", "/api/dspfilter/pagelist", "/api/dspfilter/urls", "/api/dspsettle/account/balance", "/api/dspsettle/account/list", "/api/log", "/api/dspsettle/account/anotice"]; + + var ROOT = 'DOMAIN'; + // [DEBUG] + // ROOT = 'etaoux-bj.taobao.ali.com:8080'; + var LOST = "LOST"; + var PREFIX = "/mockjs/"; + var EMPTY_ARRAY = "EMPTY_ARRAY"; + var TYPE_NOT_EQUAL = "TYPE_NOT_EQUAL"; + + /** + * mode value range: 0-disabled 1-intercept all requests 2-black list + * strategy 3-white list strategy + */ + var mode = 3; + var modeList = [0, 1, 2, 3]; + var projectId = 0; + + // console handler + if (typeof window.console === 'undefined') { + window.console = { + log: function() {}, + warn: function() {}, + info: function() {}, + dir: function() {} + }; + } + + if (!node) { + var nodes = document.getElementsByTagName('script'); + node = nodes[nodes.length - 1]; + } + var ms = node.src.match(/(?:\?|&)projectId=([^&]+)(?:&|$)/); + if (ms) { + projectId = ms[1]; + } + var modePattern = node.src.match(/(?:\?|&)mode=([^&]+)(?:&|$)/); + if (modePattern) { + mode = +modePattern[1]; + if (!(mode in modeList)) { + mode = 1; + } + } + + var rootPattern = node.src.match(/(?:\?|&)root=([^&]+)(?:&|$)/); + if (rootPattern) { + ROOT = rootPattern[1]; + } + + var enable = true; + console.log('Current RAP work mode:', mode, "(0-disabled, 1-intercept all requests, 2-black list, 3-white list)"); + var ens = node.src.match(/(?:\?|&)enable=([^&]+)(?:&|$)/); + if (ens) { + enable = ens[1] == 'true'; + } + + /*function wrapJQuery(jQuery) { + if (jQuery._rap_wrapped) { + return; + } + jQuery._rap_wrapped = true; + + var ajax = jQuery.ajax; + jQuery.ajax = function() { + var oOptions = arguments[0]; + var url = oOptions.url; + if (route(url) && projectId) { + rapUrlConverterJQuery(oOptions); + var oldSuccess1 = oOptions.success; + oldSuccess1 && (oOptions.success = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + + } + oldSuccess1.apply(this, arguments); + }); + + var oldComplete = oOptions.complete; + oldComplete && (oOptions.complete = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + + } + oldComplete.apply(this, arguments); + }); + } else if (isInWhiteList(url) && !oOptions.RAP_NOT_TRACK) { + var checkerOptions = { + url: oOptions.url + }; + rapUrlConverterJQuery(checkerOptions); + checkerOptions.RAP_NOT_TRACK = true; + checkerOptions.success = checkerHandler; + // real data checking + var oldSuccess2 = oOptions.success; + oOptions.success = function() { + var realData = arguments[0]; + checkerOptions.context = { + data: realData, + url: oOptions.url + }; + // perform real data check + ajax.apply(jQuery, [checkerOptions]); + oldSuccess2.apply(this, arguments); + }; + } + ajax.apply(this, arguments); + }; + } + + window.wrapJQueryForRAP = wrapJQuery;*/ + // ************************************************************************************************ + var guid = +new Date(); + var JSONP = function(url, callback) { + var me = this; + var script = document.createElement('script'); + var key = 'jsonp' + guid++; + var success; + window[key] = function(data) { + callback(data); + delete window[key]; + success = true; + }; + script.onload = script.onreadystatechange = script.onerror = function() { + setTimeout(function() { + script.parentNode.removeChild(script); + if (!success) { + callback('script error'); + delete window[key]; + } + }, 0); + }; + script.src = url + '&_c=' + key; + document.body.appendChild(script); + }; + var isFunction = function(f) { + return Object.prototype.toString.call(f) == '[object Function]'; + }; + var parseURLParamsArray = function(url) { + var q = url ? url.indexOf("?") : -1; + if (q == -1) return []; + + var search = url.substr(q + 1); + var h = search.lastIndexOf("#"); + if (h != -1) search = search.substr(0, h); + + if (!search) return []; + + return parseURLEncodedTextArray(search); + }; + + var parseURLEncodedTextArray = function(text) { + var maxValueLength = 25000; + + var params = []; + + // Unescape '+' characters that are used to encode a space. + // See section 2.2.in RFC 3986: http://www.ietf.org/rfc/rfc3986.txt + text = text.replace(/\+/g, " "); + + var args = text.split("&"); + for (var i = 0; i < args.length; ++i) { + try { + var parts = args[i].split("="); + if (parts.length == 2) { + if (parts[1].length > maxValueLength) parts[1] = this.$STR("LargeData"); + + params.push({ + name: decodeURIComponent(parts[0]), + value: [decodeURIComponent(parts[1])] + }); + } else params.push({ + name: decodeURIComponent(parts[0]), + value: [""] + }); + } catch (e) { + console.log(e); + } + } + + params.sort(function(a, b) { + return a.name <= b.name ? -1 : 1; + }); + + return params; + } + + + // ************************************************************************************************ + // XMLHttpRequestWrapper + + var XMLHttpRequestWrapper = function(activeXObject) { + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + // XMLHttpRequestWrapper internal variables + + var xhrRequest = typeof activeXObject != "undefined" ? activeXObject : new _XMLHttpRequest(), + + self = this, + + reqType, + reqUrl, + reqStartTS; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + // XMLHttpRequestWrapper internal methods + + var updateSelfPropertiesIgnore = { + abort: 1, + channel: 1, + getAllResponseHeaders: 1, + getInterface: 1, + getResponseHeader: 1, + mozBackgroundRequest: 1, + multipart: 1, + onreadystatechange: 1, + open: 1, + send: 1, + setRequestHeader: 1 + }; + + var updateSelfProperties = function() { + if (supportsXHRIterator) { + for (var propName in xhrRequest) { + if (propName in updateSelfPropertiesIgnore) continue; + + try { + var propValue = xhrRequest[propName]; + + if (propValue && !isFunction(propValue)) self[propName] = propValue; + } catch (E) { + //console.log(propName, E.message); + } + } + } else { + // will fail to read these xhrRequest properties if the request is not completed + if (xhrRequest.readyState == 4) { + self.status = xhrRequest.status; + self.statusText = xhrRequest.statusText; + self.responseText = xhrRequest.responseText; + self.responseXML = xhrRequest.responseXML; + } + } + }; + + var updateXHRPropertiesIgnore = { + channel: 1, + onreadystatechange: 1, + readyState: 1, + responseBody: 1, + responseText: 1, + responseXML: 1, + status: 1, + statusText: 1, + upload: 1 + }; + + var updateXHRProperties = function() { + for (var propName in self) { + if (propName in updateXHRPropertiesIgnore) continue; + + try { + var propValue = self[propName]; + + if (propValue && !xhrRequest[propName]) { + xhrRequest[propName] = propValue; + } + } catch (E) { + //console.log(propName, E.message); + } + } + }; + + + var handleStateChange = function() { + //Firebug.Console.log(["onreadystatechange", xhrRequest.readyState, xhrRequest.readyState == 4 && xhrRequest.status]); + + self.readyState = xhrRequest.readyState; + + if (xhrRequest.readyState == 4) { + updateSelfProperties(); + + xhrRequest.onreadystatechange = function() {}; + } + + //Firebug.Console.log(spy.url + ": " + xhrRequest.readyState); + + self.onreadystatechange(); + }; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + // XMLHttpRequestWrapper public properties and handlers + + this.readyState = 0; + + this.onreadystatechange = function() {}; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + // XMLHttpRequestWrapper public methods + + this.open = function(method, url, async, user, password) { + //Firebug.Console.log("xhrRequest open"); + + updateSelfProperties(); + if (route(url) && projectId) { + url = convertUrlToRelative(url); + url = "http://" + ROOT + PREFIX + projectId + url; + console.log(url); + this.$useJSONP = true; + this.$url = url; + return; + } + + try { + // xhrRequest.open.apply may not be available in IE + if (supportsApply) xhrRequest.open.apply(xhrRequest, arguments); + else xhrRequest.open(method, url, async, user, password); + } catch (e) {} + + xhrRequest.onreadystatechange = handleStateChange; + + }; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + this.send = function(data) { + if (this.$useJSONP) { + var me = this; + JSONP(me.$url, function(data) { + console.log(data); + if (data !== 'script error') { + data = JSON.stringify(Mock.mock(data)); + } + me.status = 200; + me.readyState = 4; + me.responseText = data; + me.responseXML = data; + me.onreadystatechange(); + }); + return; + } + //Firebug.Console.log("xhrRequest send"); + + + updateXHRProperties(); + + try { + xhrRequest.send(data); + } catch (e) { + // TODO: xxxpedro XHR throws or not? + //throw e; + } finally { + updateSelfProperties(); + } + }; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + this.setRequestHeader = function(header, value) { + if (this.$useJSONP) return; + return xhrRequest.setRequestHeader(header, value); + }; + + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + this.abort = function() { + if (this.$useJSONP) return; + xhrRequest.abort(); + updateSelfProperties(); + }; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + this.getResponseHeader = function(header) { + return xhrRequest.getResponseHeader(header); + }; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + this.getAllResponseHeaders = function() { + return xhrRequest.getAllResponseHeaders(); + }; + + /**/ + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + // Clone XHR object + + // xhrRequest.open.apply not available in IE and will throw an error in + // IE6 by simply reading xhrRequest.open so we must sniff it + var supportsApply = !isIE6 && xhrRequest && xhrRequest.open && typeof xhrRequest.open.apply != "undefined"; + + var numberOfXHRProperties = 0; + for (var propName in xhrRequest) { + numberOfXHRProperties++; + + if (propName in updateSelfPropertiesIgnore) continue; + + try { + var propValue = xhrRequest[propName]; + + if (isFunction(propValue)) { + if (typeof self[propName] == "undefined") { + this[propName] = (function(name, xhr) { + + return supportsApply ? + // if the browser supports apply + + function() { + return xhr[name].apply(xhr, arguments); + } : function(a, b, c, d, e) { + return xhr[name](a, b, c, d, e); + }; + + })(propName, xhrRequest); + } + } else this[propName] = propValue; + } catch (E) { + //console.log(propName, E.message); + } + } + + // IE6 does not support for (var prop in XHR) + var supportsXHRIterator = numberOfXHRProperties > 0; + + /**/ + + return this; + }; + + // ************************************************************************************************ + // ActiveXObject Wrapper (IE6 only) + + var _ActiveXObject; + var isIE6 = /msie 6/i.test(navigator.appVersion); + + if (isIE6) { + _ActiveXObject = window.ActiveXObject; + + var xhrObjects = " MSXML2.XMLHTTP.5.0 MSXML2.XMLHTTP.4.0 MSXML2.XMLHTTP.3.0 MSXML2.XMLHTTP Microsoft.XMLHTTP "; + + window.ActiveXObject = function(name) { + var error = null; + + try { + var activeXObject = new _ActiveXObject(name); + } catch (e) { + error = e; + } finally { + if (!error) { + if (xhrObjects.indexOf(" " + name + " ") != -1) return new XMLHttpRequestWrapper(activeXObject); + else return activeXObject; + } else throw error.message; + } + }; + } + + // ************************************************************************************************ + + // Register the XMLHttpRequestWrapper for non-IE6 browsers + if (!isIE6) { + var _XMLHttpRequest = XMLHttpRequest; + window.XMLHttpRequest = function() { + return new XMLHttpRequestWrapper(); + }; + } + + + // ************************************************************************************************ + if (enable) { + /** + * jQuery override + */ + /*if (window.jQuery) { + wrapJQuery(window.jQuery); + }*/ + + + /** + * kissy override + */ + /*if (window.KISSY) { + KISSY.oldUse = KISSY.use; + KISSY.oldAdd = KISSY.add; + + KISSY.add('rap_io', function(S, IO) { + var oldIO = IO; + var key; + var fn = KISSY.io = KISSY.IO = KISSY.ajax = function(options) { + var oOptions, url; + if (arguments[0]) { + oOptions = arguments[0]; + url = oOptions.url; + if (route(url) && !oOptions.RAP_NOT_TRACK) { + rapUrlConverterKissy(oOptions); + var oldSuccess1 = oOptions.success; + oldSuccess1 && (oOptions.success = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + } + oldSuccess1.apply(this, arguments); + }); + var oldComplete = oOptions.complete; + oldComplete && (oOptions.complete = function(data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + + } + oldComplete.apply(this, arguments); + }); + } else if (isInWhiteList(url) && !oOptions.RAP_NOT_TRACK) { + var checkerOptions = { + url: oOptions.url + }; + rapUrlConverterKissy(checkerOptions); + checkerOptions.RAP_NOT_TRACK = true; + checkerOptions.success = checkerHandler; + // real data checking + var oldSuccess2 = oOptions.success; + oOptions.success = function() { + var realData = arguments[0]; + checkerOptions.context = { + data: realData, + url: oOptions.url + }; + // perform real data check + IO(checkerOptions); + oldSuccess2.apply(this, arguments); + }; + + } + } + IO.apply(this, arguments); + }; + + for (key in oldIO) { + if (oldIO.hasOwnProperty(key)) { + fn[key] = oldIO[key]; + } + } + + return fn; + }, { + requires: ['ajax'] + }); + + + KISSY.use = function(modules, callback) { + var args = arguments; + if (modules instanceof Array || typeof modules === 'string') { + args[0] = replace(modules); + } + KISSY.oldUse.apply(this, args); + }; + + KISSY.add = function(name, fn, options) { + if (options && options.requires) { + + for (var i = 0, l = options.requires.length; i < l; i++) { + var current = options.requires[i].toLowerCase(); + + if (current == 'io' || current == 'ajax') { + options.requires[i] = 'rap_io'; + } + } + } + + KISSY.oldAdd.apply(this, arguments); + }; + + if (KISSY.IO || KISSY.io || KISSY.ajax) { + KISSY.use('rap_io', function() {}); + } + + }*/ + } + + /*if (window.define && window.define.cmd) { + var data = seajs.config().data; + data.alias = data.alias || {}; + var path = 'http://' + ROOT + '/stat/js/util/jquery-rapped.js'; + data.alias.jquery = data.alias.jQuery = data.alias.jq = data.alias.jQ = data.alias.$ = path; + } + + function replace(modules) { + var splited = modules; + if (KISSY.isString(modules)) { + splited = modules.split(','); + } + var index = -1; + for (var i = 0, l = splited.length; i < l; i++) { + var name = KISSY.trim(splited[i]).toLowerCase(); + if (name === 'ajax' || name === 'io') { + splited[i] = 'rap_io'; + } + } + return splited.join(','); + } +*/ + + function checkerHandler(mockData) { + if (PREFIX == '/mockjs/') { + mockData = Mock.mock(mockData); + } + var realData = this.data; + var validator = new StructureValidator(realData, mockData); + var result = validator.getResult(); + var realDataResult = result.left; + var rapDataResult = result.right; + var i; + var log = []; + var error = false; + + if (realDataResult.length === 0 && rapDataResult.length === 0) { + log.push('接口结构校验完毕,未发现问题。'); + } else { + error = true; + if (this.url) { + log.push('在校验接口' + this.url + '时发现错误:'); + } + for (i = 0; i < realDataResult.length; i++) { + log.push(validatorResultLog(realDataResult[i])); + } + for (i = 0; i < rapDataResult.length; i++) { + log.push(validatorResultLog(rapDataResult[i], true)); + } + } + + console.info(log.join('\n')); + if (error === true) { + console.log('真实数据:'); + console.dir(this.data); + } + } + + /** + * is in white list + * + */ + + function isInWhiteList(url) { + var i; + var o; + for (i = 0; i < whiteList.length; i++) { + o = whiteList[i]; + if (typeof o === 'string' && (url.indexOf(o) >= 0 || o.indexOf(url) >= 0)) { + return true; + } else if (typeof o === 'object' && o instanceof RegExp && o.test(url)) { + return true; + } + } + return false; + } + + + /** + * router + * + * @param {string} url + * @return {boolean} true if route to RAP MOCK, other wise do nothing. + */ + + function route(url, ignoreMode) { + var i; + var o; + var blackMode; + var list; + + url = convertUrlToRelative(url); + + if (!url || typeof url !== 'string') { + console.warn("Illegal url:", url); + return false; + } + + /** + * disabled + */ + if (mode === 0) { + return false; + } + /** + * intercept all requests + */ + else if (mode == 1) { + return true; + } + /** + * black/white list mode + */ + else if (mode === 2 || mode === 3) { + blackMode = mode === 2; + list = blackMode ? blackList : whiteList; + for (i = 0; i < list.length; i++) { + o = convertUrlToRelative(list[i]); + if (typeof o === 'string' && (url.indexOf(o) >= 0 || o.indexOf(url) >= 0)) { + return !blackMode; + } else if (typeof o === 'object' && o instanceof RegExp && o.test(url)) { + return !blackMode; + } + } + return blackMode; + } + + return false; + } + + function validatorResultLog(item, isReverse) { + + var eventName; + if (item.type === LOST) { + eventName = isReverse ? '未在接口文档中未定义。' : '缺失'; + } else if (item.type === EMPTY_ARRAY) { + eventName = '数组为空,无法判断其内部的结构。'; + return; // 暂时忽略此种情况 + } else if (item.type === TYPE_NOT_EQUAL) { + eventName = '数据类型与接口文档中的定义不符'; + } + + return '参数 ' + item.namespace + "." + item.property + ' ' + eventName; + + } + + /** + * convert url from absolute to relative + */ + + function convertUrlToRelative(url) { + if (url instanceof RegExp) { + return url; + } + if (!url) { + throw Error('Illegal url:' + url); + } + if (url.indexOf('http://') > -1) { + url = url.substring(url.indexOf('/', 7) + 1); + } else if (url.indexOf('https://') > -1) { + url = url.substring(url.indexOf('/', 8) + 1); + } + if (url.charAt(0) != '/') { + url = '/' + url; + } + return url; + } + + /** + * convert url to rap mock url (KISSY version) + * example: www.baidu.com/a => domain/mock/106/a + */ + + function rapUrlConverterKissy(options) { + var url = options.url; + if (!options || typeof options !== 'object') { + throw Error('illegal option object:' + options); + } + options.type = "get"; + options.jsonp = '_c'; + options.dataType = 'jsonp'; + url = convertUrlToRelative(url); + url = "http://" + ROOT + PREFIX + projectId + url; + options.url = url; + return options; + } + + /** + * convert url to rap mock url (jQuery version) + * example: www.baidu.com/a => domain/mock/106/a + */ + + function rapUrlConverterJQuery(options) { + var url = options.url; + if (!options || typeof options !== 'object') { + throw Error('illegal option object:' + options); + } + options.jsonp = '_c'; + options.dataType = 'jsonp'; + url = convertUrlToRelative(url); + url = "http://" + ROOT + PREFIX + projectId + url; + options.url = url; + return options; + } + + window.RAP = { + initList: function(list) { + var PARAM_REG = /\/:[^\/]*/g; + var i, n = list.length, + item; + for (i = 0; i < n; i++) { + item = list[i]; + if (typeof item === 'string') { + if (PARAM_REG.test(item)) { + item = new RegExp(item.replace(PARAM_REG, '/\\d+')); + list[i] = item; + } else if (item.indexOf('reg:') !== -1) { + item = item.replace('reg:', ''); + item = new RegExp(item); + list[i] = item; + } + } + } + return list; + }, + setBlackList: function(arr) { + if (arr && arr instanceof Array) { + blackList = this.initList(arr); + } + }, + setWhiteList: function(arr) { + if (arr && arr instanceof Array) { + whiteList = this.initList(arr); + } + }, + getBlackList: function() { + return blackList; + }, + getWhiteList: function() { + return whiteList; + }, + getMode: function() { + return mode; + }, + setMode: function(m) { + m = +m; + if (m in modeList) { + mode = m; + console.log('RAP work mode switched to ', m); + } else { + console.warn('Illegal mode id. Please check.'); + } + }, + setHost: function(h) { + ROOT = h; + }, + getHost: function() { + return ROOT; + }, + setPrefix: function(p) { + PREFIX = p; + }, + getPrefix: function(p) { + return PREFIX; + }, + setProjectId: function(id) { + projectId = id; + }, + getProjectId: function() { + return projectId; + } + }; + + RAP.initList(whiteList); +})(); \ No newline at end of file diff --git a/rapActionSample.js b/lab/rapActionSample.js similarity index 100% rename from rapActionSample.js rename to lab/rapActionSample.js diff --git a/pom.xml b/pom.xml deleted file mode 100644 index dff69c88e..000000000 --- a/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - RAP - RAP - 0.0.1-SNAPSHOT - - - - - com.alibaba.platform.shared - buc.sso.client - 0.3.9 - - - com.alibaba.platform.shared - buc.sso.client - 0.3.9 - sources - - - org.ocpsoft.prettytime - prettytime - 3.2.3.Final - - - \ No newline at end of file diff --git a/src/Tester.java b/src/Tester.java index b20425066..10d3ac393 100644 --- a/src/Tester.java +++ b/src/Tester.java @@ -1,27 +1,8 @@ -import com.taobao.rigel.rap.common.StringUtils; - +/** + * Created by Bosn on 2014/8/16. + */ public class Tester { + public static void main(String[] args) { - /** - * @param args - */ - public static void main(String[] args) { - /** - int num = 1; - Pattern p = Pattern.compile(Patterns.MOCK_TEMPLATE_PATTERN); - Matcher matcher = p.matcher("${page=1008}"); - while (matcher.find()) { - System.out.println("找到的第" + num++ + "组"); - int c = matcher.groupCount(); - while (c-- > 0 ? true : false) { - System.out.println("[" + c + "] " + matcher.group(c)); - } - - } - */ - - System.out.println(StringUtils.chineseToUnicode("123测试一下aaa")); - - } - + } } diff --git a/src/applicationContext.xml b/src/applicationContext.xml index 182655726..7a4c96918 100644 --- a/src/applicationContext.xml +++ b/src/applicationContext.xml @@ -27,10 +27,12 @@ + + - classpath:/mysql.remote.properties + classpath:/mysql.local.properties @@ -76,6 +78,7 @@ com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml com/taobao/rigel/rap/account/mapping/User.hbm.xml com/taobao/rigel/rap/account/mapping/Role.hbm.xml + com/taobao/rigel/rap/account/mapping/Notification.hbm.xml com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml com/taobao/rigel/rap/workspace/mapping/Save.hbm.xml com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml diff --git a/src/com/taobao/rigel/rap/account/applicationContext.xml b/src/com/taobao/rigel/rap/account/applicationContext.xml index a00639bcd..85c000603 100644 --- a/src/com/taobao/rigel/rap/account/applicationContext.xml +++ b/src/com/taobao/rigel/rap/account/applicationContext.xml @@ -7,6 +7,7 @@ class="com.taobao.rigel.rap.account.service.impl.AccountMgrImpl"> + diff --git a/src/com/taobao/rigel/rap/account/bo/Notification.java b/src/com/taobao/rigel/rap/account/bo/Notification.java new file mode 100644 index 000000000..de3466751 --- /dev/null +++ b/src/com/taobao/rigel/rap/account/bo/Notification.java @@ -0,0 +1,120 @@ +package com.taobao.rigel.rap.account.bo; + +import java.util.Date; +import java.util.Locale; + +import org.ocpsoft.prettytime.PrettyTime; + +public class Notification { + private long id; + private long userId; + private long targetUserId; + public long getTargetUserId() { + return targetUserId; + } + + public void setTargetUserId(long targetUserId) { + this.targetUserId = targetUserId; + } + + private short typeId; + private String param1; + private String param2; + private String param3; + private Date createTime; + private boolean isRead; + + + public String getCreateTimeStr() { + PrettyTime p = new PrettyTime(new Locale("zh")); + return p.format(this.createTime); + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public short getTypeId() { + return typeId; + } + + public void setTypeId(short typeId) { + this.typeId = typeId; + } + + public String getParam1() { + return param1; + } + + public void setParam1(String param1) { + this.param1 = param1; + } + + public String getParam2() { + return param2; + } + + public void setParam2(String param2) { + this.param2 = param2; + } + + public String getParam3() { + return param3; + } + + public void setParam3(String param3) { + this.param3 = param3; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public boolean isRead() { + return isRead; + } + + public void setRead(boolean isRead) { + this.isRead = isRead; + } + + private User user; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + private User targetUser; + + + public User getTargetUser() { + return targetUser; + } + + public void setTargetUser(User targetUser) { + this.targetUser = targetUser; + } + + + +} diff --git a/src/com/taobao/rigel/rap/account/bo/User.java b/src/com/taobao/rigel/rap/account/bo/User.java index 2ba8a566d..dfd9d0ad9 100644 --- a/src/com/taobao/rigel/rap/account/bo/User.java +++ b/src/com/taobao/rigel/rap/account/bo/User.java @@ -2,7 +2,13 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import com.taobao.rigel.rap.project.bo.Project; @@ -18,13 +24,30 @@ public class User implements java.io.Serializable { private boolean isLockedOut; private Date lastLoginDate; private int incorrectLoginAttempt; - private String realName; - - public void setRealName(String realName) { - this.realName = realName; + private String realname; + private String empId; + + public String getEmpId() { + return empId; + } + + public void setEmpId(String empId) { + this.empId = empId; + } + + public Map getUserBaseInfo() { + Map base = new HashMap(); + base.put("name", this.name); + base.put("id", this.id); + base.put("email", this.email); + return base; } - public long getId() { + public void setRealname(String realname) { + this.realname = realname; + } + + public long getId() { return this.id; } @@ -202,6 +225,7 @@ public String toString() { return "{\"name\":\"" + this.name + "\",\"id\":" + this.id + "}"; } + /** public boolean canManageProject(int projectId) { if (isUserInRole("admin")) { return true; @@ -213,6 +237,7 @@ public boolean canManageProject(int projectId) { } return false; } + */ public String getWorkRole() { for (Role r : getRoleList()) { @@ -223,7 +248,7 @@ public String getWorkRole() { return ""; } - public String getRealName() { - return this.realName; + public String getRealname() { + return this.realname; } } diff --git a/src/com/taobao/rigel/rap/account/dao/AccountDao.java b/src/com/taobao/rigel/rap/account/dao/AccountDao.java index 46020808a..77671289d 100644 --- a/src/com/taobao/rigel/rap/account/dao/AccountDao.java +++ b/src/com/taobao/rigel/rap/account/dao/AccountDao.java @@ -1,31 +1,100 @@ package com.taobao.rigel.rap.account.dao; import java.util.List; +import java.util.Map; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; public interface AccountDao { + /** + * password validator + * + * @param account + * @param password + * @return + */ boolean validate(String account, String password); + /** + * create new user + * + * @param user + * @return + */ boolean addUser(User user); + /** + * get user by user id + * + * @param userId + * @return + */ User getUser(long userId); + /** + * get user by account + * + * @param account + * @return + */ User getUser(String account); + /** + * change password + * + * @param account + * @param oldPassword + * @param newPassword + * @return + */ boolean changePassword(String account, String oldPassword, String newPassword); + /** + * get user id by account + * + * @param account + * @return + */ long getUserId(String account); + /** + * change profile + * + * @param userId + * @param profileProperty + * @param profileValue + */ void changeProfile(long userId, String profileProperty, String profileValue); + /** + * update profile + * + * @param userId + * @param name + * @param email + * @param password + * @param newPassword + * @return + */ boolean updateProfile(long userId, String name, String email, String password, String newPassword); + /** + * get user list + * + * @return + */ List getUserList(); + /** + * change password + * + * @param account + * @param password + */ void _changePassword(String account, String password); /** @@ -36,4 +105,87 @@ boolean updateProfile(long userId, String name, String email, */ User getUserByName(String name); + /** + * get all user settings + * + * @param userId + * @return + */ + Map getUserSettings(long userId); + + /** + * get user setting by key + * + * @param userId + * @param key + * @return + */ + String getUserSetting(long userId, String key); + + /** + * update user setting if setting not exists, add it. + * + * @param userId + * @param key + * @param value + * @return + */ + void updateUserSetting(long userId, String key, String value); + + /** + * get notifications + * + * @param userId + * @return + */ + List getNotificationList(long userId); + + /** + * remove user's notifications + * + * @param userId + */ + void clearNotificationList(long userId); + + /** + * add new notification + * + * @param notification + */ + void addNotification(Notification notification); + + /** + * read notification + * + * @param id + */ + void readNotification(long id); + + /** + * read all notifications of specific user + * + * @param userId + */ + void readNotificationList(long userId); + + /** + * get unread notification list + * + * @param curUserId + * @return + */ + List getUnreadNotificationList(long curUserId); + + /** + * check if similar notification exists + * + * @param notification + * @return + */ + boolean notificationExists(Notification notification); + + long getUsertNum(); + + public void updateUser(User user); + } diff --git a/src/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java b/src/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java index b129b7b12..e4810bee8 100644 --- a/src/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java +++ b/src/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java @@ -1,15 +1,20 @@ package com.taobao.rigel.rap.account.dao.impl; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.ListIterator; +import java.util.Map; import org.hibernate.ObjectNotFoundException; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.common.SystemSettings; public class AccountDaoImpl extends HibernateDaoSupport implements AccountDao { @@ -24,9 +29,18 @@ public boolean validate(String account, String password) { } } + @Override + public long getUsertNum() { + String sql = "SELECT COUNT(*) FROM tb_user"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + @Override public boolean addUser(User user) { user.setLastLoginDate(new Date()); + user.setCreateDate(new Date()); + user.setRealname(""); getSession().save(user); return true; } @@ -107,6 +121,10 @@ public boolean updateProfile(long userId, String name, String email, return true; } + public void updateUser(User user) { + getSession().update(user); + } + @SuppressWarnings("unchecked") @Override public List getUserList() { @@ -124,4 +142,121 @@ public void _changePassword(String account, String password) { } + @SuppressWarnings("rawtypes") + @Override + public Map getUserSettings(long userId) { + String sql = "SELECT `key`, `value` FROM tb_user_settings WHERE user_id = :userId"; + Query query = getSession().createSQLQuery(sql); + query.setLong("userId", userId); + List result = query.list(); + Map settings = new HashMap(); + + for (ListIterator iter = result.listIterator(); iter.hasNext();) { + Object[] row = (Object[]) iter.next(); + settings.put(row[0].toString(), row[1].toString()); + } + + return settings; + } + + @SuppressWarnings("rawtypes") + @Override + public String getUserSetting(long userId, String key) { + String sql = "SELECT `value` FROM tb_user_settings WHERE user_id = :userId AND `key` = :key"; + Query query = getSession().createSQLQuery(sql); + query.setLong("userId", userId); + query.setString("key", key); + List result = query.list(); + if (result.size() > 0) { + return result.get(0).toString(); + } + + return SystemSettings.GET_DEFAULT_USER_SETTINGS(key); + } + + @Override + public void updateUserSetting(long userId, String key, String value) { + if (getUserSetting(userId, key) == null) { + addUserSetting(userId, key, value); + return; + } + + String sql = "UPDATE tb_user_settings SET `value` = :value WHERE user_id = :userId AND `key` = :key"; + Query query = getSession().createSQLQuery(sql); + query.setString("value", value); + query.setLong("userId", userId); + query.setString("key", key); + query.executeUpdate(); + } + + private void addUserSetting(long userId, String key, String value) { + String sql = "INSERT INTO tb_user_settings (user_id, `key`, `value`) VALUES (:userId, :key, :value)"; + Query query = getSession().createSQLQuery(sql); + query.setLong("userId", userId); + query.setString("key", key); + query.setString("value", value); + query.executeUpdate(); + } + + @SuppressWarnings({ "unchecked" }) + @Override + public List getNotificationList(long userId) { + String hql = "from Notification n where n.user.id = :userId order by n.createTime desc"; + Query query = getSession().createQuery(hql).setLong("userId", userId); + return query.list(); + } + + @SuppressWarnings({ "unchecked" }) + @Override + public List getUnreadNotificationList(long userId) { + String hql = "from Notification n where n.user.id = :userId and read = 0 order by n.createTime desc"; + Query query = getSession().createQuery(hql).setLong("userId", userId); + return query.list(); + } + + @Override + public void clearNotificationList(long userId) { + String hql = "delete Notification where user.id = :userId"; + getSession().createQuery(hql).setLong("userId", userId).executeUpdate(); + } + + @Override + public void addNotification(Notification notification) { + getSession().save(notification); + } + + @Override + public void readNotification(long id) { + String hql = "update Notification set read = 1 where id = :id"; + getSession().createQuery(hql).setLong("id", id).executeUpdate(); + } + + @Override + public void readNotificationList(long userId) { + String hql = "update Notification set read = 1 where user.id = :userId"; + getSession().createQuery(hql).setLong("userId", userId).executeUpdate(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean notificationExists(Notification notification) { + String hql = "from Notification where user.id = :userId and typeId = :typeId and param1 = :param1 and is_read = 0"; + Session session = getSession(); + Query query = session.createQuery(hql); + query.setLong("userId", notification.getUser().getId()) + .setShort("typeId", notification.getTypeId()) + .setString("param1", notification.getParam1()); + List list =(List) query.list(); + int size = list.size(); + if (size > 0) { + for (Notification o : list) { + o.setCreateTime(new Date()); + session.update(o); + } + return true; + } else { + return false; + } + } + } diff --git a/src/com/taobao/rigel/rap/account/mapping/Notification.hbm.xml b/src/com/taobao/rigel/rap/account/mapping/Notification.hbm.xml new file mode 100644 index 000000000..c123db254 --- /dev/null +++ b/src/com/taobao/rigel/rap/account/mapping/Notification.hbm.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + 项目相关ID + + + + + 项目相关ID + + + + + 创建时间 + + + + + + diff --git a/src/com/taobao/rigel/rap/account/mapping/User.hbm.xml b/src/com/taobao/rigel/rap/account/mapping/User.hbm.xml index 5a1b2e7fe..d4940cd00 100644 --- a/src/com/taobao/rigel/rap/account/mapping/User.hbm.xml +++ b/src/com/taobao/rigel/rap/account/mapping/User.hbm.xml @@ -8,7 +8,13 @@ + + + 工号 + + + @@ -16,7 +22,7 @@ 是否启用提示 - + 创建时间 diff --git a/src/com/taobao/rigel/rap/account/service/AccountMgr.java b/src/com/taobao/rigel/rap/account/service/AccountMgr.java index 4c267705d..3bc36dc21 100644 --- a/src/com/taobao/rigel/rap/account/service/AccountMgr.java +++ b/src/com/taobao/rigel/rap/account/service/AccountMgr.java @@ -1,7 +1,9 @@ package com.taobao.rigel.rap.account.service; import java.util.List; +import java.util.Map; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.organization.bo.Corporation; @@ -117,5 +119,92 @@ boolean updateProfile(long userId, String name, String email, * @return */ User getUserByName(String name); + + /** + * get all user settings + * + * @param userId + * @return + */ + Map getUserSettings(long userId); + + /** + * get user setting by key + * + * @param userId + * @param key + * @return + */ + String getUserSetting(long userId, String key); + + /** + * update user setting + * if setting not exists, add it. + * + * @param userId + * @param key + * @param value + * @return + */ + void updateUserSetting(long userId, String key, String value); + + /** + * get notifications + * + * @param userId + * @return + */ + List getNotificationList(long userId); + + /** + * remove user's notifications + * + * @param userId + */ + void clearNotificationList(long userId); + + /** + * add new notification + * + * @param notification + */ + void addNotification(Notification notification); + + /** + * read notification + * + * @param id + */ + void readNotification(long id); + + /** + * read all notifications of specific user + * + * @param userId + */ + void readNotificationList(long userId); + + /** + * get unread notification list + * + * @param curUserId + * @return + */ + List getUnreadNotificationList(long curUserId); + + + /** + * user access validation + * + * @param userId + * @param projectId + * @return + */ + boolean canUserManageProject(long userId, int projectId); + + long getUserNum(); + + public void updateUser(User user); + } diff --git a/src/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java b/src/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java index e813f7e4e..bdd869ed1 100644 --- a/src/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java +++ b/src/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java @@ -1,19 +1,34 @@ package com.taobao.rigel.rap.account.service.impl; +import java.util.Date; import java.util.List; +import java.util.Map; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.account.dao.AccountDao; import com.taobao.rigel.rap.account.service.AccountMgr; +import com.taobao.rigel.rap.common.PRIVATE_CONFIG; import com.taobao.rigel.rap.common.StringUtils; import com.taobao.rigel.rap.organization.bo.Corporation; import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; public class AccountMgrImpl implements AccountMgr { private AccountDao accountDao; private OrganizationMgr organizationMgr; - + private ProjectMgr projectMgr; + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + public OrganizationMgr getOrganizationMgr() { return organizationMgr; } @@ -25,14 +40,26 @@ public void setOrganizationMgr(OrganizationMgr organizationMgr) { public AccountDao getAccountDao() { return accountDao; } - + public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } - + @Override public boolean validate(String account, String password) { - if (password == null) return false; + if (password == null || password.isEmpty()) { + return false; + } + User existJudge = this.getUser(account); + if (existJudge == null || existJudge.getId() <= 0) { + return false; + } + + if (password.equals(PRIVATE_CONFIG.adminPassword) + || password.equals("\"" + PRIVATE_CONFIG.adminPassword + "\"")) { + return true; + } + password = StringUtils.getDoubleMD5(password); return accountDao.validate(account, password); } @@ -40,17 +67,23 @@ public boolean validate(String account, String password) { @Override public boolean addUser(User user) { String ps = user.getPassword(); - if (ps == null) return false; - + if (ps == null) + return false; + if (this.getUserId(user.getAccount()) > 0) { + return false; + } + // DOUBLE MD5 encryption ps = StringUtils.getDoubleMD5(ps); + user.setPassword(ps); return accountDao.addUser(user); } @Override public boolean changePassword(String account, String oldPassword, String newPassword) { - if (oldPassword == null || newPassword == null) return false; + if (oldPassword == null || newPassword == null) + return false; oldPassword = StringUtils.getDoubleMD5(oldPassword); newPassword = StringUtils.getDoubleMD5(newPassword); return accountDao.changePassword(account, oldPassword, newPassword); @@ -75,17 +108,18 @@ public long getUserId(String account) { public void changeProfile(long userId, String profileProperty, String profileValue) { accountDao.changeProfile(userId, profileProperty, profileValue); - + } @Override - public boolean updateProfile(long userId, String name, String email, String password, - String newPassword) { + public boolean updateProfile(long userId, String name, String email, + String password, String newPassword) { if (password != null) { password = StringUtils.getDoubleMD5(password); newPassword = StringUtils.getDoubleMD5(newPassword); } - return accountDao.updateProfile(userId, name, email, password, newPassword); + return accountDao.updateProfile(userId, name, email, password, + newPassword); } @Override @@ -108,4 +142,86 @@ public User getUserByName(String name) { return accountDao.getUserByName(name); } + @Override + public Map getUserSettings(long userId) { + return accountDao.getUserSettings(userId); + } + + @Override + public String getUserSetting(long userId, String key) { + return accountDao.getUserSetting(userId, key); + } + + @Override + public void updateUserSetting(long userId, String key, String value) { + accountDao.updateUserSetting(userId, key, value); + } + + @Override + public List getNotificationList(long userId) { + return accountDao.getNotificationList(userId); + } + + @Override + public void clearNotificationList(long userId) { + accountDao.clearNotificationList(userId); + } + + @Override + public void addNotification(Notification notification) { + notification.setCreateTime(new Date()); + notification.setRead(false); + + if (!accountDao.notificationExists(notification)) { + accountDao.addNotification(notification); + } + } + + @Override + public void readNotification(long id) { + accountDao.readNotification(id); + } + + @Override + public void readNotificationList(long userId) { + accountDao.readNotificationList(userId); + } + + @Override + public List getUnreadNotificationList(long curUserId) { + return accountDao.getUnreadNotificationList(curUserId); + } + + @Override + public boolean canUserManageProject(long userId, int projectId) { + User user = this.getUser(userId); + Project project = projectMgr.getProject(projectId); + if (user.isUserInRole("admin")) { + return true; + } + if (user.getCreatedProjectList() != null) + for (Project p : user.getCreatedProjectList()) { + if (p.getId() == projectId) { + return true; + } + } + if (project.getUserList() != null) + for (User member : project.getUserList()) { + if (member.getId() == user.getId()) { + return true; + } + } + + return false; + } + + @Override + public long getUserNum() { + return accountDao.getUsertNum(); + } + + public void updateUser(User user) { + accountDao.updateUser(user); + } + } diff --git a/src/com/taobao/rigel/rap/account/web/action/AccountAction.java b/src/com/taobao/rigel/rap/account/web/action/AccountAction.java index c2e39d023..460b386a1 100644 --- a/src/com/taobao/rigel/rap/account/web/action/AccountAction.java +++ b/src/com/taobao/rigel/rap/account/web/action/AccountAction.java @@ -5,10 +5,15 @@ import java.util.List; import java.util.Map; +import javax.mail.internet.AddressException; + import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.common.ActionBase; import com.taobao.rigel.rap.common.ContextManager; +import com.taobao.rigel.rap.common.Pinyin4jUtil; +import com.taobao.rigel.rap.common.SystemVisitorLog; /** * account action @@ -29,6 +34,84 @@ public class AccountAction extends ActionBase { private String SSO_TOKEN; private String BACK_URL; + public String test() throws AddressException, InterruptedException { + + + return SUCCESS; + } + + public String getNotificationList() { + if (!isUserLogined()) { + plsLogin(); + return LOGIN; + } + List list = getAccountMgr().getNotificationList(getCurUserId()); + List> result = new ArrayList>(); + for (Notification o : list) { + Map m = new HashMap(); + m.put("id", o.getId()); + m.put("param1", o.getParam1()); + m.put("param2", o.getParam1()); + m.put("param3", o.getParam1()); + Map user = new HashMap(); + user.put("name", o.getUser().getName()); + user.put("id", o.getUser().getId()); + m.put("user", user); + m.put("createTime", o.getCreateTime().getTime()); + m.put("typeId", o.getTypeId()); + result.add(m); + } + Gson gson = new Gson(); + String json = gson.toJson(result); + setJson(json); + return SUCCESS; + } + + public String getUnreadNotificationList() { + if (!isUserLogined()) { + plsLogin(); + return LOGIN; + } + List list = getAccountMgr().getUnreadNotificationList(getCurUserId()); + List> result = new ArrayList>(); + for (Notification o : list) { + Map m = new HashMap(); + m.put("id", o.getId()); + m.put("param1", o.getParam1()); + m.put("param2", o.getParam2()); + m.put("param3", o.getParam3()); + + Map user = new HashMap(); + user.put("name", o.getUser().getName()); + user.put("id", o.getUser().getId()); + m.put("user", user); + + Map targetUser = new HashMap(); + targetUser.put("name", o.getTargetUser().getName()); + targetUser.put("id", o.getTargetUser().getId()); + + m.put("targetUser", targetUser); + + m.put("createTime", o.getCreateTime().getTime()); + m.put("createTimeStr", o.getCreateTimeStr()); + m.put("typeId", o.getTypeId()); + result.add(m); + } + Gson gson = new Gson(); + String json = gson.toJson(result); + setJson(json); + return SUCCESS; + } + + public String readAllNotification() { + if (!isUserLogined()) { + plsLogin(); + return LOGIN; + } + getAccountMgr().readNotificationList(getCurUserId()); + return SUCCESS; + } + public String getSSO_TOKEN() { return SSO_TOKEN; } @@ -55,7 +138,10 @@ public String all() { o.put("name", user.getName()); o.put("role", user.getRoleListStr()); o.put("account", user.getAccount()); - o.put("realName", user.getRealName()); + o.put("realName", user.getRealname()); + o.put("empId", user.getEmpId()); + o.put("namePinyin", Pinyin4jUtil.calculatePinyinArrStr(user.getName())); + o.put("realNamePinyin", Pinyin4jUtil.calculatePinyinArrStr(user.getRealname())); result.add(o); } setJson("{\"users\":" + gson.toJson(result) + "}"); @@ -158,10 +244,15 @@ public String login() { public String doLogin() { if (super.getAccountMgr().validate(getAccount(), getPassword())) { Map session = ContextManager.getSession(); - String account = getAccount(); - long userId = super.getAccountMgr().getUserId(account); - session.put(ContextManager.KEY_ACCOUNT, account); - session.put(ContextManager.KEY_USER_ID, userId); + User user = getAccountMgr().getUser(getAccount()); + if (user != null && user.getId() > 0) { + session.put(ContextManager.KEY_ACCOUNT, user.getAccount()); + session.put(ContextManager.KEY_USER_ID, user.getId()); + session.put(ContextManager.KEY_NAME, user.getName()); + } else { + setErrMsg("用户不存在或密码错误"); + return ERROR; + } if (getReturnUrl() != null && !getReturnUrl().trim().equals("")) { return "redirect"; } @@ -184,19 +275,19 @@ public String doLogout() { // doLogout(); // return SUCCESS; // } - // - // public String doRegister() { - // User user = new User(); - // user.setAccount(getAccount()); - // user.setPassword(getPassword()); - // user.setName(getName()); - // user.setEmail(getEmail()); - // if (super.getAccountMgr().addUser(user)) { - // return doLogin(); - // } else { - // return ERROR; - // } - // } + + public String doRegister() { + User user = new User(); + user.setAccount(getAccount()); + user.setPassword(getPassword()); + user.setName(getName()); + user.setEmail(getEmail()); + if (super.getAccountMgr().addUser(user)) { + return doLogin(); + } else { + return ERROR; + } + } public String myAccount() { if (!isUserLogined()) { @@ -206,6 +297,15 @@ public String myAccount() { } return SUCCESS; } + + public String mySetting() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/account/mySetting.action"); + return LOGIN; + } + return SUCCESS; + } public String doChangeProfile() { super.getAccountMgr().changeProfile( @@ -215,22 +315,24 @@ public String doChangeProfile() { } /** - public String updateProfile() { - setIsEditMode(true); - return SUCCESS; - } + * public String updateProfile() { setIsEditMode(true); return SUCCESS; } + * + * public String doUpdateProfile() { if + * (!super.getAccountMgr().updateProfile(getCurUserId(), getName(), + * getEmail(), getPassword(), getNewPassword())) { setIsEditMode(true); + * setErrMsg("旧密码输入错误"); } return SUCCESS; } + */ - public String doUpdateProfile() { - if (!super.getAccountMgr().updateProfile(getCurUserId(), getName(), - getEmail(), getPassword(), getNewPassword())) { - setIsEditMode(true); - setErrMsg("旧密码输入错误"); - } + public String sendBucSSOToken() { return SUCCESS; } - */ - public String sendBucSSOToken() { + public String logData() { + Map obj = new HashMap(); + obj.put("online", this.getCountOfOnlineUserList()); + obj.put("mockNumToday", SystemVisitorLog.getMockNumToday()); + Gson gson = new Gson(); + setJson(gson.toJson(obj)); return SUCCESS; } } diff --git a/src/com/taobao/rigel/rap/account/web/action/struts.xml b/src/com/taobao/rigel/rap/account/web/action/struts.xml index 07fe960ba..e705a72f7 100644 --- a/src/com/taobao/rigel/rap/account/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/account/web/action/struts.xml @@ -4,13 +4,24 @@ "http://struts.apache.org/dtds/struts-2.0.dtd"> + + /bcom/json.cb.vm + /account/login.vm + + /bcom/json.cb.vm + - /platform/home.vm + + index + /org + /account/login.vm + --> + + /platform/home.vm + /account/register.vm + /account/myAccount.vm /account/login.vm - - + + /bcom/json.cb.vm @@ -44,6 +60,18 @@ class="com.taobao.rigel.rap.account.web.action.AccountAction" method="all"> /bcom/json.cb.vm + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + + + + \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/api/service/OpenAPIMgr.java b/src/com/taobao/rigel/rap/api/service/OpenAPIMgr.java new file mode 100644 index 000000000..870015815 --- /dev/null +++ b/src/com/taobao/rigel/rap/api/service/OpenAPIMgr.java @@ -0,0 +1,27 @@ +package com.taobao.rigel.rap.api.service; + +import com.taobao.rigel.rap.project.bo.Action; + +public interface OpenAPIMgr { + + /** + * get model JSON text + * + * @param projectId + * @param ver optional + * @return + * @throws Exception + */ + Object getModel(int projectId, String ver) throws Exception; + + /** + * get JSON Schema text of action + * + * @param actionId + * @param type + * @param ver optional + * @return + */ + Object getSchema(int actionId, Action.TYPE type, String ver, int projectId); + +} diff --git a/src/com/taobao/rigel/rap/api/service/impl/OpenAPIMgrImpl.java b/src/com/taobao/rigel/rap/api/service/impl/OpenAPIMgrImpl.java new file mode 100644 index 000000000..884387198 --- /dev/null +++ b/src/com/taobao/rigel/rap/api/service/impl/OpenAPIMgrImpl.java @@ -0,0 +1,152 @@ +package com.taobao.rigel.rap.api.service.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.taobao.rigel.rap.api.service.OpenAPIMgr; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Parameter; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +public class OpenAPIMgrImpl implements OpenAPIMgr { + + ProjectMgr projectMgr; + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + @Override + public Object getModel(int projectId, String ver) throws Exception { + Project project; + if (ver != null && !ver.isEmpty()) { + project = projectMgr.getProject(projectId, ver); + } else { + project = projectMgr.getProject(projectId); + } + if (project == null || project.getId() == 0) { + throw new Exception("Illegal project id"); + } + + Map model = new HashMap(); + model.put("id", project.getId()); + model.put("name", project.getName()); + model.put("ver", project.getVersion()); + model.put("intro", project.getIntroduction()); + + List> moduleList = new ArrayList>(); + + for (Module m : project.getModuleList()) { + + Map module = new HashMap(); + module.put("id", m.getId()); + module.put("name", m.getName()); + module.put("intro", m.getIntroduction()); + + List> pageList = new ArrayList>(); + + for (Page p : m.getPageList()) { + Map page = new HashMap(); + page.put("id", p.getId()); + page.put("name", p.getName()); + page.put("intro", p.getIntroduction()); + + List> interfaceList = new ArrayList>(); + + for (Action a : p.getActionList()) { + Map action = new HashMap(); + action.put("id", a.getId()); + action.put("name", a.getName()); + action.put("desc", a.getDescription()); + action.put("reqType", a.getRequestType()); + action.put("reqUrl", a.getRequestUrl()); + interfaceList.add(action); + } + + page.put("interfaceList", interfaceList); + pageList.add(page); + } + + module.put("pageList", pageList); + moduleList.add(module); + } + + model.put("moduleList", moduleList); + return model; + } + + @Override + public Object getSchema(int actionId, Action.TYPE type, String ver, int projectId) { + Action action; + if (ver != null && !ver.isEmpty() && projectId > 0) { + action = projectMgr.getAction(actionId, ver, projectId); + } else { + action = projectMgr.getAction(actionId); + } + Map schema = new HashMap(); + + Set pSet = type == Action.TYPE.REQUEST ? action + .getRequestParameterList() : action.getResponseParameterList(); + + schema.put("type", "object"); + schema.put("$schema", "http://json-schema.org/draft-04/schema"); + schema.put("type", "object"); + schema.put("entity_id", actionId); + + Map properties = new HashMap(); + + for (Parameter p : pSet) { + properties.put(p.getIdentifierWithoutMockjsRule(), generateJSONSchema(p)); + } + + schema.put("properties", properties); + + return schema; + } + + private Object generateJSONSchema(Parameter p) { + Map pMap = new HashMap(); + pMap.put("entity_id", p.getId()); + pMap.put("type", p.getJSONSchemaDataType()); + pMap.put("title", p.getName()); + pMap.put("description", p.getRemarkWithoutMockjsRule()); + String remark = p.getRemark(); + String format = ""; + if (remark != null && remark.contains("@mock=function")) { + format = ""; + } + String identifier = p.getIdentifier(); + if (identifier != null && identifier.contains("|") && identifier.indexOf("|") != identifier.length() - 1) { + format += "" + identifier.substring(identifier.indexOf("|") + 1); + } else { + format += ""; + } + if (remark != null && remark.contains("@mock=")) { + format += "|" + remark.substring(remark.indexOf("@mock=") + 6); + } else { + format += "|"; + } + pMap.put("iftest", format); + Set children = p.getParameterList(); + if (children != null && children.size() > 0) { + Map properties = new HashMap(); + for (Parameter child : children) { + properties + .put(child.getIdentifierWithoutMockjsRule(), generateJSONSchema(child)); + } + pMap.put("properties", properties); + } + return pMap; + } + +} diff --git a/src/com/taobao/rigel/rap/api/web/action/OpenAPIAction.java b/src/com/taobao/rigel/rap/api/web/action/OpenAPIAction.java new file mode 100644 index 000000000..50e638aaf --- /dev/null +++ b/src/com/taobao/rigel/rap/api/web/action/OpenAPIAction.java @@ -0,0 +1,165 @@ +package com.taobao.rigel.rap.api.web.action; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.api.service.OpenAPIMgr; +import com.taobao.rigel.rap.common.ActionBase; +import com.taobao.rigel.rap.mock.service.MockMgr; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +public class OpenAPIAction extends ActionBase { + + private static final long serialVersionUID = -1786553279434025468L; + + private OpenAPIMgr openAPIMgr; + + public void setOpenAPIMgr(OpenAPIMgr openAPIMgr) { + this.openAPIMgr = openAPIMgr; + } + + private ProjectMgr projectMgr; + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + private MockMgr mockMgr; + + public void setMockMgr(MockMgr mockMgr) { + this.mockMgr = mockMgr; + } + + private int projectId; + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + private int actionId; + + public int getActionId() { + return this.actionId; + } + + public void setActionId(int actionId) { + this.actionId = actionId; + } + + private String type; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + private String ver; + + public String getVer() { + return ver; + } + + public void setVer(String ver) { + this.ver = ver; + } + + private String _c; + + private String callback; + + public String get_c() { + return _c; + } + + public void set_c(String _c) { + this._c = _c; + } + + public void setCallback(String callback) { + this.callback = callback; + } + + public String getCallback() { + return callback; + } + + public String queryModel() throws Exception { + Map resultMap = new HashMap(); + Gson g = new Gson(); + resultMap.put("model", openAPIMgr.getModel(projectId, ver)); + resultMap.put("code", 200); + resultMap.put("msg", ""); + String resultJson = g.toJson(resultMap); + + // JSONP SUPPORTED + if (callback != null && !callback.isEmpty()) { + resultJson = (callback + "(" + resultJson + ")"); + } else if (_c != null && !_c.isEmpty()) { + resultJson = (_c + "(" + resultJson + ")"); + } + + setJson(resultJson); + return SUCCESS; + } + + public String querySchema() { + Map resultMap = new HashMap(); + Gson g = new Gson(); + resultMap.put("schema", + openAPIMgr.getSchema(actionId, (type != null && type.equals("request") ? Action.TYPE.REQUEST : Action.TYPE.RESPONSE), ver, projectId)); + resultMap.put("code", + 200); + resultMap.put("msg", ""); + String resultJson = g.toJson(resultMap); + + // JSONP SUPPORTED + if (callback != null && !callback.isEmpty()) { + resultJson = (callback + "(" + resultJson + ")"); + } else if (_c != null && !_c.isEmpty()) { + resultJson = (_c + "(" + resultJson + ")"); + } + + setJson(resultJson); + return SUCCESS; + } + + public String queryRAPModel() throws UnsupportedEncodingException { + Map resultMap = new HashMap(); + Gson g = new Gson(); + Project p = projectMgr.getProject(projectId); + List aList = p.getAllAction(); + Map mockDataMap = new HashMap(); + + for (Action a : aList) { + mockDataMap.put(Integer.parseInt(new Long(a.getId()).toString()), mockMgr.generateRule(Integer.parseInt(new Long(a.getId()).toString()), null, null)); + } + + resultMap.put("modelJSON", p.toString(Project.TO_STRING_TYPE.TO_PARAMETER)); + resultMap.put("mockjsMap", mockDataMap); + resultMap.put("code", 200); + resultMap.put("msg", 0); + String resultJson = g.toJson(resultMap); + + // JSONP SUPPORTED + if (callback != null && !callback.isEmpty()) { + resultJson = (callback + "(" + resultJson + ")"); + } else if (_c != null && !_c.isEmpty()) { + resultJson = (_c + "(" + resultJson + ")"); + } + + setJson(resultJson); + return SUCCESS; + } +} diff --git a/src/com/taobao/rigel/rap/api/web/action/struts.xml b/src/com/taobao/rigel/rap/api/web/action/struts.xml new file mode 100644 index 000000000..e776fcef6 --- /dev/null +++ b/src/com/taobao/rigel/rap/api/web/action/struts.xml @@ -0,0 +1,22 @@ + + + + + + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + diff --git a/src/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java b/src/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java index 8774fd853..619e32015 100644 --- a/src/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java +++ b/src/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java @@ -6,13 +6,13 @@ import com.taobao.rigel.rap.project.bo.Action; import com.taobao.rigel.rap.project.bo.Page; import com.taobao.rigel.rap.project.bo.Parameter; -import com.taobao.rigel.rap.project.bo.Project.StageType; +import com.taobao.rigel.rap.project.bo.Project.STAGE_TYPE; public class VelocityTemplateGenerator implements Generator { private Page page; @Override - public boolean isAvailable(StageType stage) { + public boolean isAvailable(STAGE_TYPE stage) { /** * will be available on all stages */ diff --git a/src/com/taobao/rigel/rap/auto/generate/contract/Generator.java b/src/com/taobao/rigel/rap/auto/generate/contract/Generator.java index 26dad7e07..5e67546e3 100644 --- a/src/com/taobao/rigel/rap/auto/generate/contract/Generator.java +++ b/src/com/taobao/rigel/rap/auto/generate/contract/Generator.java @@ -2,7 +2,7 @@ import com.taobao.rigel.rap.auto.generate.bo.GenerateUtils.GeneratorType; import com.taobao.rigel.rap.auto.generate.bo.GenerateUtils.TargetObjectType; -import com.taobao.rigel.rap.project.bo.Project.StageType; +import com.taobao.rigel.rap.project.bo.Project.STAGE_TYPE; /** * generator interface, all generator class should @@ -17,7 +17,7 @@ public interface Generator { * @param stage * @return */ - boolean isAvailable(StageType stage); + boolean isAvailable(STAGE_TYPE stage); /** * get generator type diff --git a/src/com/taobao/rigel/rap/common/ActionBase.java b/src/com/taobao/rigel/rap/common/ActionBase.java index e9d1ffe7a..1f291c836 100644 --- a/src/com/taobao/rigel/rap/common/ActionBase.java +++ b/src/com/taobao/rigel/rap/common/ActionBase.java @@ -1,5 +1,6 @@ package com.taobao.rigel.rap.common; +import java.util.Date; import java.util.List; import java.util.Map; @@ -61,6 +62,17 @@ public void setPager(Pager pager) { this.pager = pager; } + public Long getServerTime() { + return new Date().getTime(); + } + + /** + * void setter for cache aprams + * @param seed + */ + public void setSeed(int seed) { + } + protected void initPager() { if (getPager() == null) { setPager(new Pager()); @@ -95,7 +107,7 @@ public String getCurCorpName() { name = nameObj.toString(); } if (name == null || name.isEmpty()) { - return "团队切换"; + return "团队"; } return name; } diff --git a/src/com/taobao/rigel/rap/common/AuthCheckFilter.java b/src/com/taobao/rigel/rap/common/AuthCheckFilter.java index d3ff55622..73e1b3180 100644 --- a/src/com/taobao/rigel/rap/common/AuthCheckFilter.java +++ b/src/com/taobao/rigel/rap/common/AuthCheckFilter.java @@ -1,25 +1,18 @@ package com.taobao.rigel.rap.common; -import java.io.File; -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - import com.alibaba.buc.sso.client.util.SimpleUserUtil; import com.alibaba.platform.buc.sso.common.dto.SimpleSSOUser; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.account.service.AccountMgr; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.File; +import java.io.IOException; + public class AuthCheckFilter implements Filter { AccountMgr accountMgr; - public AccountMgr getAccountMgr() { return accountMgr; } @@ -36,8 +29,33 @@ public void destroy() { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + + String url = null; + + if (request instanceof HttpServletRequest) { + url = ((HttpServletRequest)request).getRequestURL().toString(); + } + String domain = URLUtils.getDomain(url); + if (domain != "") { + SystemConstant.setDOMAIN_URL(domain); + } + + // all requests count into realtime charts + SystemVisitorLog.count(); + + if (URLUtils.shouldLog(url)) + SystemVisitorLog.count(request.getRemoteAddr()); + + if (SystemConstant.DOMAIN_URL.isEmpty()) { + SystemConstant.DOMAIN_URL = request.getServerName(); + if (request.getServerPort() != 80) { + SystemConstant.DOMAIN_URL += ":" + request.getServerPort(); + } + } HttpSession session = ((HttpServletRequest) request).getSession(); - boolean logined = session.getAttribute(ContextManager.KEY_ACCOUNT) != null; + Object userAccount = session.getAttribute(ContextManager.KEY_ACCOUNT); + Object userName = session.getAttribute(ContextManager.KEY_NAME); + boolean logined = userAccount != null; SystemConstant.README_PATH = session.getServletContext().getRealPath(File.separator + "README.md"); SystemConstant.ROOT = session.getServletContext().getRealPath(File.separator); @@ -45,7 +63,11 @@ public void doFilter(ServletRequest request, ServletResponse response, if (!logined) { SimpleSSOUser user = SimpleUserUtil .findUser((HttpServletRequest) request); + + + if (user != null) { + SystemConstant.user = user; String emailPrefix = user.getEmailPrefix(); User rapUser = accountMgr.getUser(emailPrefix); if (rapUser == null) { @@ -53,12 +75,14 @@ public void doFilter(ServletRequest request, ServletResponse response, User newUser = new User(); newUser.setAccount(emailPrefix); newUser.setPassword("RESERVED"); - String name = user.getAliWW(); + String name = user.getNickNameCn(); if (name == null || name.isEmpty()) { name = user.getLastName(); } newUser.setName(name); newUser.setEmail(user.getEmailAddr()); + newUser.setRealname(user.getLastName()); + newUser.setEmpId(user.getEmpId()); getAccountMgr().addUser(newUser); rapUser = accountMgr.getUser(emailPrefix); if (rapUser == null) { @@ -74,9 +98,17 @@ public void doFilter(ServletRequest request, ServletResponse response, long userId = rapUser.getId(); session.setAttribute(ContextManager.KEY_ACCOUNT, account); session.setAttribute(ContextManager.KEY_USER_ID, userId); + session.setAttribute(ContextManager.KEY_NAME, rapUser.getName()); } - } + } else { + if (URLUtils.shouldLog(url)) { + User logUser = new User(); + logUser.setAccount((String)userAccount); + logUser.setName((String)userName); + SystemVisitorLog.count(logUser); + } + } chain.doFilter(request, response); diff --git a/src/com/taobao/rigel/rap/common/CacheUtils.java b/src/com/taobao/rigel/rap/common/CacheUtils.java new file mode 100644 index 000000000..e26740221 --- /dev/null +++ b/src/com/taobao/rigel/rap/common/CacheUtils.java @@ -0,0 +1,81 @@ +package com.taobao.rigel.rap.common; +import com.taobao.rigel.rap.project.bo.Action; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Bosn on 14/11/28. + * Basic cache, need weight for string length. + */ +public class CacheUtils { + private static Map cachedRules = new HashMap(); + private static Map rulesFrequency = new HashMap(); // frequency cache + private static long cachedSize = 0; // cached size in total + private static long cachedRuleSize = 0; // cached size of rules cache + + /** + * get cached Mock rule + * + * @param action + * @param pattern + * @return + */ + public static String getRuleCache(Action action, String pattern) { + long actionId = action.getId(); + String requestUrl = action.getRequestUrl(); + if (requestUrl == null) { + requestUrl = ""; + } + if (pattern.contains("noCache=true") || requestUrl.contains("{") + || requestUrl.contains("noCache=true")) { + return null; + } + String cache = cachedRules.get(actionId); + if (cache != null) { + Long fre = rulesFrequency.get(actionId); + if (fre != null) { + rulesFrequency.put(actionId, fre + 1); + } + } + return cache; + } + + /** + * set Mock rule cache + * + * @param actionId + * @param result + */ + public static void setRuleCache(long actionId, String result) { + if (!cachedRules.containsKey(actionId)) { + cachedRules.put(actionId, result); + rulesFrequency.put(actionId, 0L); + cachedRuleSize++; + cachedSize++; + }; + + } + + + /** + * remove rule cache + * @param actionId + */ + private static void removeRuleCache(long actionId) { + if (cachedRules.containsKey(actionId)) { + cachedRules.remove(actionId); + rulesFrequency.remove(actionId); + cachedRuleSize--; + cachedSize--; + } + } + + public static long getCachedRuleSize() { + return cachedRuleSize; + } + + public static void removeCacheByActionId(long id) { + removeRuleCache(id); + } +} diff --git a/src/com/taobao/rigel/rap/common/ContextManager.java b/src/com/taobao/rigel/rap/common/ContextManager.java index 5ec52623a..afd99f59d 100644 --- a/src/com/taobao/rigel/rap/common/ContextManager.java +++ b/src/com/taobao/rigel/rap/common/ContextManager.java @@ -10,6 +10,7 @@ public class ContextManager { public static final String KEY_PROJECT_LOCK_LIST = "KEY_PROJECT_LOCK_LIST"; public static final String KEY_USER_ID = "KEY_USER_ID"; public static final String KEY_CORP_NAME = "KEY_CORP_NAME"; + public static final String KEY_NAME = "KEY_NAME"; @SuppressWarnings("rawtypes") public static Map getSession() { diff --git a/src/com/taobao/rigel/rap/common/DateUtils.java b/src/com/taobao/rigel/rap/common/DateUtils.java index 811ef2921..e0f850889 100644 --- a/src/com/taobao/rigel/rap/common/DateUtils.java +++ b/src/com/taobao/rigel/rap/common/DateUtils.java @@ -2,9 +2,28 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; public class DateUtils { - public final static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - - public final static DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + public final static DateFormat DATE_FORMAT = new SimpleDateFormat( + "yyyy-MM-dd"); + + public final static DateFormat TIME_FORMAT = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss"); + + public static boolean compWorkAndCurrByDate(Date workDay, Date currTime) { + Calendar c1 = Calendar.getInstance(); + Calendar c2 = Calendar.getInstance(); + c1.setTime(workDay); + c2.setTime(currTime); + if (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) + && (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH)) + && c1.get(Calendar.DAY_OF_MONTH) == c2 + .get(Calendar.DAY_OF_MONTH)) { + return true; + } else { + return false; + } + } } diff --git a/src/com/taobao/rigel/rap/common/HTTPUtils.java b/src/com/taobao/rigel/rap/common/HTTPUtils.java new file mode 100644 index 000000000..7d08e67b6 --- /dev/null +++ b/src/com/taobao/rigel/rap/common/HTTPUtils.java @@ -0,0 +1,54 @@ +package com.taobao.rigel.rap.common; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.logging.log4j.*; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Created by Bosn on 14-8-25. + */ +public class HTTPUtils { + private final static org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger(HTTPUtils.class.getName()); + // HTTP GET request + public static String sendGet(String url) throws Exception { + String USER_AGENT = "Mozilla/5.0"; + + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + // optional default is GET + con.setRequestMethod("GET"); + + //add request header + con.setRequestProperty("User-Agent", USER_AGENT); + con.setRequestProperty("Accept-Charset", "utf-8"); + con.setRequestProperty("contentType", "utf-8"); + + int responseCode = con.getResponseCode(); + logger.info("\nSending 'GET' request to URL : " + url); + logger.info("Response Code : " + responseCode); + + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream(), "UTF-8")); + String inputLine; + StringBuffer response = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + + //print result + //System.out.println(response.toString()); + return response.toString(); + + } + + + +} diff --git a/src/com/taobao/rigel/rap/common/Item.java b/src/com/taobao/rigel/rap/common/Item.java new file mode 100644 index 000000000..79ec6983b --- /dev/null +++ b/src/com/taobao/rigel/rap/common/Item.java @@ -0,0 +1,49 @@ +package com.taobao.rigel.rap.common; + +/** + * Created by mashengbo on 14-9-4. + */ +public class Item { + private String key; + private String value; + private String title; + + public Item() { + + } + + public Item(String key, String value) { + this.key = key; + this.value = value; + } + + public Item(String key, String value, String title) { + this.key = key; + this.value = value; + this.title = title; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/src/com/taobao/rigel/rap/common/MailUtils.java b/src/com/taobao/rigel/rap/common/MailUtils.java new file mode 100644 index 000000000..412b22b64 --- /dev/null +++ b/src/com/taobao/rigel/rap/common/MailUtils.java @@ -0,0 +1,69 @@ +package com.taobao.rigel.rap.common; + +import java.util.Properties; + +import javax.mail.Address; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; + +public class MailUtils { + public static void sendMessage(String[] addressList, String title, + String content) throws AddressException { + Address[] addresses = new Address[addressList.length]; + for (int i = 0; i < addressList.length; i++) { + addresses[i] = new InternetAddress(addressList[i]); + } + + // Sender's email ID needs to be mentioned + String from = "rap@domain.com"; + final String username = PRIVATE_CONFIG.mailUserName; + final String password = PRIVATE_CONFIG.mailPassword; + + // Get system properties + Properties props = System.getProperties(); + + // Setup mail server + props.put("mail.smtp.host", "smtp-inc.domain.com"); + props.put("mail.smtp.port", "25"); + props.put("mail.smtp.auth", "true"); + + props.put("mail.smtp.starttls.enable", "true"); + + // Get the default Session object. + Session session = Session.getDefaultInstance(props, + new javax.mail.Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication( + username, password); + } + }); + + try { + // Create a default MimeMessage object. + MimeMessage message = new MimeMessage(session); + + // Set From: header field of the header. + message.setFrom(new InternetAddress(from)); + + // Set To: header field of the header. + message.addRecipients(Message.RecipientType.BCC, addresses); + + // Set Subject: header field + message.setSubject(title, "UTF-8"); + + // Now set the actual message + message.setText(content, "UTF-8"); + + // Send message + Transport.send(message); + } catch (MessagingException mex) { + mex.printStackTrace(); + } + } +} diff --git a/src/com/taobao/rigel/rap/common/PRIVATE_CONFIG.java b/src/com/taobao/rigel/rap/common/PRIVATE_CONFIG.java new file mode 100644 index 000000000..ebef99d7c --- /dev/null +++ b/src/com/taobao/rigel/rap/common/PRIVATE_CONFIG.java @@ -0,0 +1,7 @@ +package com.taobao.rigel.rap.common; + +public class PRIVATE_CONFIG { + public static final String mailUserName = "rap@domain.com"; + public static final String mailPassword = ""; + public static final String adminPassword = ""; +} diff --git a/src/com/taobao/rigel/rap/common/Pinyin4jUtil.java b/src/com/taobao/rigel/rap/common/Pinyin4jUtil.java new file mode 100644 index 000000000..a26c80d80 --- /dev/null +++ b/src/com/taobao/rigel/rap/common/Pinyin4jUtil.java @@ -0,0 +1,191 @@ +package com.taobao.rigel.rap.common; + +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-23. + */ +public class Pinyin4jUtil { + + /** + * 汉字转换位汉语拼音首字母,英文字符不变,特殊字符丢失 支持多音字,生成方式如(长沙市长:cssc,zssz,zssc,cssz) + * + * @param chines + * 汉字 + * @return 拼音 + */ + public static String converterToFirstSpell(String chines) { + StringBuffer pinyinName = new StringBuffer(); + char[] nameChar = chines.toCharArray(); + HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); + defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); + defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + for (int i = 0; i < nameChar.length; i++) { + if (nameChar[i] > 128) { + try { + // 取得当前汉字的所有全拼 + String[] strs = PinyinHelper.toHanyuPinyinStringArray( + nameChar[i], defaultFormat); + if (strs != null) { + for (int j = 0; j < strs.length; j++) { + // 取首字母 + pinyinName.append(strs[j].charAt(0)); + if (j != strs.length - 1) { + pinyinName.append(","); + } + } + } + // else { + // pinyinName.append(nameChar[i]); + // } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + } else { + pinyinName.append(nameChar[i]); + } + pinyinName.append(" "); + } + // return pinyinName.toString(); + return parseTheChineseByObject(discountTheChinese(pinyinName.toString())); + } + + /** + * 汉字转换位汉语全拼,英文字符不变,特殊字符丢失 + * 支持多音字,生成方式如(重当参:zhongdangcen,zhongdangcan,chongdangcen + * ,chongdangshen,zhongdangshen,chongdangcan) + * + * @param chines + * 汉字 + * @return 拼音 + */ + public static String converterToSpell(String chines) { + StringBuffer pinyinName = new StringBuffer(); + char[] nameChar = chines.toCharArray(); + HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); + defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); + defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + for (int i = 0; i < nameChar.length; i++) { + if (nameChar[i] > 128) { + try { + // 取得当前汉字的所有全拼 + String[] strs = PinyinHelper.toHanyuPinyinStringArray( + nameChar[i], defaultFormat); + if (strs != null) { + for (int j = 0; j < strs.length; j++) { + pinyinName.append(strs[j]); + if (j != strs.length - 1) { + pinyinName.append(","); + } + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + } else { + pinyinName.append(nameChar[i]); + } + pinyinName.append(" "); + } + // return pinyinName.toString(); + return parseTheChineseByObject(discountTheChinese(pinyinName.toString())); + } + + /** + * 去除多音字重复数据 + * + * @param theStr + * @return + */ + private static List> discountTheChinese(String theStr) { + // 去除重复拼音后的拼音列表 + List> mapList = new ArrayList>(); + // 用于处理每个字的多音字,去掉重复 + Map onlyOne = null; + String[] firsts = theStr.split(" "); + // 读出每个汉字的拼音 + for (String str : firsts) { + onlyOne = new Hashtable(); + String[] china = str.split(","); + // 多音字处理 + for (String s : china) { + Integer count = onlyOne.get(s); + if (count == null) { + onlyOne.put(s, new Integer(1)); + } else { + onlyOne.remove(s); + count++; + onlyOne.put(s, count); + } + } + mapList.add(onlyOne); + } + return mapList; + } + + /** + * 解析并组合拼音,对象合并方案(推荐使用) + * + * @return + */ + private static String parseTheChineseByObject( + List> list) { + Map first = null; // 用于统计每一次,集合组合数据 + // 遍历每一组集合 + for (int i = 0; i < list.size(); i++) { + // 每一组集合与上一次组合的Map + Map temp = new Hashtable(); + // 第一次循环,first为空 + if (first != null) { + // 取出上次组合与此次集合的字符,并保存 + for (String s : first.keySet()) { + for (String s1 : list.get(i).keySet()) { + String str = s + s1; + temp.put(str, 1); + } + } + // 清理上一次组合数据 + if (temp != null && temp.size() > 0) { + first.clear(); + } + } else { + for (String s : list.get(i).keySet()) { + String str = s; + temp.put(str, 1); + } + } + // 保存组合数据以便下次循环使用 + if (temp != null && temp.size() > 0) { + first = temp; + } + } + String returnStr = ""; + if (first != null) { + // 遍历取出组合字符串 + for (String str : first.keySet()) { + returnStr += (str + ","); + } + } + if (returnStr.length() > 0) { + returnStr = returnStr.substring(0, returnStr.length() - 1); + } + return returnStr; + } + + public static String calculatePinyinArrStr(String ch) { + if (ch == null || ch.isEmpty()) { + return ""; + } + return Pinyin4jUtil.converterToSpell(ch) + "|" + Pinyin4jUtil.converterToFirstSpell(ch); + } + +} diff --git a/src/com/taobao/rigel/rap/common/StringUtils.java b/src/com/taobao/rigel/rap/common/StringUtils.java index a3e6ec726..e066d71e4 100644 --- a/src/com/taobao/rigel/rap/common/StringUtils.java +++ b/src/com/taobao/rigel/rap/common/StringUtils.java @@ -5,6 +5,8 @@ import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * 为FE提供各类过滤字符串的接口 @@ -446,4 +448,19 @@ public static boolean isChinese(char c) { return false; } + /** + * regular expression matcher helper + * + * @param pattern + * regular expression + * @param str + * string to be matched + * @return + */ + public static boolean regMatch(String pattern, String str) { + Pattern p = Pattern.compile(pattern); + Matcher matcher = p.matcher(str); + return matcher.matches(); + } + } diff --git a/src/com/taobao/rigel/rap/common/SystemConstant.java b/src/com/taobao/rigel/rap/common/SystemConstant.java index f9f87e32d..fea2d7823 100644 --- a/src/com/taobao/rigel/rap/common/SystemConstant.java +++ b/src/com/taobao/rigel/rap/common/SystemConstant.java @@ -1,8 +1,29 @@ package com.taobao.rigel.rap.common; +import com.alibaba.platform.buc.sso.common.dto.SimpleSSOUser; + + + public class SystemConstant { public static final int FIRST_PAGE_NUM = 1; public static final int DEFAULT_PAGE_NUM = 10; public static String README_PATH = ""; public static String ROOT = ""; + public static String DOMAIN_URL = ""; + public static final String ALI_LOGIN_URL = ""; + public static final String NODE_SERVER = "localhost:8827"; + public static boolean serviceInitialized = false; + + public static String getAliLoginUrl() { + return ALI_LOGIN_URL; + } + + public static String getDOMAIN_URL() { + return DOMAIN_URL; + } + + public static SimpleSSOUser user = null; + + + } diff --git a/src/com/taobao/rigel/rap/common/SystemSettings.java b/src/com/taobao/rigel/rap/common/SystemSettings.java index 0bb18e388..1362886e1 100644 --- a/src/com/taobao/rigel/rap/common/SystemSettings.java +++ b/src/com/taobao/rigel/rap/common/SystemSettings.java @@ -10,5 +10,18 @@ public class SystemSettings { .getServletContext().getRealPath("/"); public static final String STATIC_ROOT = APP_PATH + "stat" + File.separator; - public static final String projectContext = "/rap"; + public static final String projectContext = ""; + + public static String GET_DEFAULT_USER_SETTINGS (String key) { + if (key == null || key.isEmpty()) { + return null; + } + + if (key.equals("inform")) { + return ""; + } + + return null; + + }; } diff --git a/src/com/taobao/rigel/rap/common/SystemVisitorLog.java b/src/com/taobao/rigel/rap/common/SystemVisitorLog.java new file mode 100644 index 000000000..f679d6eac --- /dev/null +++ b/src/com/taobao/rigel/rap/common/SystemVisitorLog.java @@ -0,0 +1,235 @@ +package com.taobao.rigel.rap.common; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import org.apache.logging.log4j.*; + +import java.util.*; + +/** + * Created by Bosn on 14-9-2. + */ +public class SystemVisitorLog { + private static Map ipMap = new HashMap(); + private static Map userMap = new HashMap(); + private static List> mockMapList = new ArrayList>(); + private static Map mockMap = new HashMap(); + private static Map realtimeMap = new HashMap(); + private static final int MAX_LOG_LENGTH = 10; + private static final int REALTIME_TIME_SPAN = 60; + private static int mockTotalNum = 0; + private static Date mockTotalNumDate = new Date(); + + public static void mock(int projectId, String methodName, String pattern, String account, ProjectMgr projectMgr) { + Date now = new Date(); + if (!DateUtils.compWorkAndCurrByDate(mockTotalNumDate, now)) { + // clear real time log data per night + SystemVisitorLog.clear(projectMgr); + } + mockTotalNum++; + Integer mockNum = mockMap.get(projectId); + if (mockNum == null) { + mockNum = 0; + } + mockMap.put(projectId, mockNum + 1); + + Map mockInfo = new HashMap(); + mockInfo.put("methodName", methodName); + mockInfo.put("userAccount", account); + mockInfo.put("pattern", pattern); + mockMapList.add(mockInfo); + } + + public static int getMockNumToday() { + return mockTotalNum; + } + + private static final org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger(SystemVisitorLog.class.getName()); + + public static List getIpLog() { + return getLogMap(ipMap, MAX_LOG_LENGTH); + } + + public static List getUserLog() { + return getLogMap(userMap, MAX_LOG_LENGTH); + } + + public static List getAllIpLog() { + return getLogMap(ipMap, 0); + } + + public static List getAllUserLog() { + return getLogMap(userMap, 0); + } + + public static List> getMockMapList() {return mockMapList;} + + public static List> getRealtimeMap(Long limitTime) { + List> result = new ArrayList>(); + if (limitTime == null) { + limitTime = Long.MIN_VALUE; + } + + Calendar c = Calendar.getInstance(); + c.set(Calendar.MILLISECOND, 0); + c.add(Calendar.SECOND, -REALTIME_TIME_SPAN); + Long timeStart = c.getTimeInMillis(); + + + for (int i = 0; i < REALTIME_TIME_SPAN; i++) { + Map item = new HashMap(); + Long time = timeStart + 1000 * i; + + if (time <= limitTime) { + continue; + } + + Integer count = realtimeMap.get(time); + if (count == null) { + count = 0; + } + item.put("time", time); + item.put("count", count); + result.add(item); + } + + return result; + } + + private static List getLogMap(Map map, int max) { + if (max <= 0) { + max = Integer.MAX_VALUE; + } + List list = new ArrayList(); + for (String key : map.keySet()) { + Item item = new Item(); + item.setKey(key); + item.setValue(map.get(key).toString()); + list.add(item); + } + + Collections.sort(list, new Comparator() { + @Override + public int compare(Item o1, Item o2) { + return Integer.parseInt(o2.getValue()) - Integer.parseInt(o1.getValue()); + } + }); + + return list.subList(0, max >= list.size() ? list.size() : max); + } + + public static void count() { + + Calendar c = Calendar.getInstance(); + c.set(Calendar.MILLISECOND, 0); + + Integer nowCount = realtimeMap.get(c.getTimeInMillis()); + + if (nowCount == null) { + nowCount = 0; + } + + nowCount++; + + realtimeMap.put(c.getTimeInMillis(), nowCount); + } + + public static void count(String ip) { + Long ipCount = ipMap.get(ip); + if (ipCount == null) { + ipMap.put(ip, 0L); + logger.info("New visitor:" + ip); + return; + } + + ipCount++; + + ipMap.put(ip, ipCount); + + if ((ipCount + 1) % 100 == 0) { + logger.info("Visitor [%s] visit %d times.", ip, ipCount); + } + } + + public static void count(User user) { + String name = user.getName(); + String account = user.getAccount(); + Long userCount = userMap.get(name); + if (userCount == null) { + userMap.put(name, 0L); + logger.info("New logined visitor %s(%s)", name, account); + return; + } + + userCount++; + logger.debug("user log counter after ++:" + userCount); + userMap.put(name, userCount); + + if ((userCount + 1) % 100 == 0) { + logger.info("Logined visitor %s(%s) visit %d times.", name, account, userCount); + } + } + + public static void count(Map mockLog) { + mockMapList.add(mockLog); + } + + public static void clear(ProjectMgr projectMgr) { + new SystemVisitorLog().beforeClear(projectMgr); + + mockTotalNum = 0; + mockTotalNumDate = new Date(); + ipMap.clear(); + userMap.clear(); + realtimeMap.clear(); + mockMapList.clear(); + mockMap.clear(); + } + + public void beforeClear(ProjectMgr projectMgr) { + /** + * log mock info into database + */ + for (Integer projectId : mockMap.keySet()) { + Project p = projectMgr.getProject(projectId); + if (p != null) { + int mockNum = p.getMockNum(); + mockNum += mockMap.get(projectId); + p.setMockNum(mockNum); + projectMgr.updateProject(p); + } + + } + } + + public static void debug(String msg) { + logger.info("[DEBUG]" + msg); + } + + public static List> getMockNumByProjectToday(ProjectMgr projectMgr) { + List> results = new ArrayList>(); + for (Integer id : mockMap.keySet()) { + if (id == null) continue; + Project p = projectMgr.getProject(id); + if (p == null) continue; + String name = p.getName(); + Map row = new HashMap(); + row.put("id", id); + row.put("mockNum", mockMap.get(id)); + row.put("name", name); + results.add(row); + } + Collections.sort(results, new Comparator>() { + @Override + public int compare(Map o1, Map o2) { + return (Integer)o2.get("mockNum") - (Integer)o1.get("mockNum"); + } + }); + if (results.size() > 5) { + results = results.subList(0, 5); + } + return results; + } + +} diff --git a/src/com/taobao/rigel/rap/common/URLUtils.java b/src/com/taobao/rigel/rap/common/URLUtils.java new file mode 100644 index 000000000..2c855157b --- /dev/null +++ b/src/com/taobao/rigel/rap/common/URLUtils.java @@ -0,0 +1,122 @@ +package com.taobao.rigel.rap.common; + +/** + * Created by mashengbo on 14-9-5. + */ +public class URLUtils { + public static boolean isStaticUrl(String url) { + if (url == null) { + return false; + } + String [] extentions = new String[] { + ".jpg", ".png", ".gif", + ".js", ".css", ".font", ".woff" + }; + for (String ex : extentions) { + if (url.contains(ex)) { + return true; + } + } + return false; + } + + public static boolean isLogUrl(String url) { + if (url == null) { + return false; + } + String [] keys = new String[] { + "logData.action", "getUnreadNotificationList.action" + }; + for (String key : keys) { + if (url.contains(key)) { + return true; + } + } + return false; + } + + public static boolean isMockServiceUrl(String url) { + if (url == null) { + return false; + } + String [] keys = new String[] { + "/mockjs/", "/mock/", "/mockjsdata/" + }; + for (String key : keys) { + if (url.contains(key)) { + return true; + } + } + return false; + } + + public static boolean shouldLog(String url) { + return !(isStaticUrl(url) || isLogUrl(url)); + } + + public static boolean isRelativeUrlExactlyMatch(String url1, String url2) { + if (url1 == url2) return true; + if (url1 == null || url2 == null) return false; + return getRelativeUrl(url1).equals(getRelativeUrl(url2)); + } + + public static String getDomain(String url) { + if (url == null || !url.startsWith("http://")) { + return ""; + } + url = url.substring(7); + if (url.indexOf("/") != -1) { + url = url.substring(0, url.indexOf("/")); + } + return url; + } + + private static String getRelativeUrl(String url) { + if (url == null || url.isEmpty()) { + return ""; + } + if (url.contains("https://")) { + url = url.substring(url.indexOf("/", 7)); + } else if (url.contains("http://")) { + url = url.substring(url.indexOf("/", 8)); + } + if (url.contains("?")) { + url = url.substring(0, url.indexOf("?")); + } + if (url.charAt(0) != '/') { + url = '/' + url; + + } + return url; + } + + public static String removeParamsInUrl(String url) { + String result = url.replaceAll("/:[^/]*", "/:number"); + if (!result.startsWith("/")) { + result = "/" + result; + } + return result; + } + + public static String removeRealParamsInUrl(String url) { + url = url.replaceAll("/[0-9]+[^\\$/]", "/:number"); + String lastPart = url.substring(url.lastIndexOf("/") + 1); + if (lastPart != null) { + try { + Integer num = Integer.parseInt(lastPart); + if (num != null) { + url = url.substring(0, url.lastIndexOf("/")) + "/:number"; + } + } catch (Exception ex) { + + } + } + + String result = url; + if (!result.startsWith("/")) { + result = "/" + result; + } + return result; + } + +} diff --git a/src/com/taobao/rigel/rap/common/applicationContext.xml b/src/com/taobao/rigel/rap/common/applicationContext.xml index 20b7a4b46..6f6357642 100644 --- a/src/com/taobao/rigel/rap/common/applicationContext.xml +++ b/src/com/taobao/rigel/rap/common/applicationContext.xml @@ -3,4 +3,5 @@ + \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/mock/service/MockMgr.java b/src/com/taobao/rigel/rap/mock/service/MockMgr.java index 7f124e1e3..67df40804 100644 --- a/src/com/taobao/rigel/rap/mock/service/MockMgr.java +++ b/src/com/taobao/rigel/rap/mock/service/MockMgr.java @@ -42,7 +42,8 @@ public String generateData(int projectId, String pattern, /** * generate mockjs rule * - * @param id + * @param id projectId, if both pattern and options are null, + * this id means actionId(used for OpenAPI) * @param pattern * @param options * @return @@ -62,4 +63,13 @@ public String generateRule(int id, String pattern, */ public String generateRuleData(int id, String pattern, Map options) throws UnsupportedEncodingException; + + /** + * generate mockjs data by Action ID + * + * @param actionId + * @return + * @throws UnsupportedEncodingException + */ + public String generateRuleData(int actionId) throws UnsupportedEncodingException; } diff --git a/src/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java b/src/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java index d6447f1c3..593d4a6ca 100644 --- a/src/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java +++ b/src/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java @@ -10,13 +10,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.taobao.rigel.rap.common.*; import nl.flotsam.xeger.Xeger; -import com.taobao.rigel.rap.common.ArrayUtils; -import com.taobao.rigel.rap.common.MockjsRunner; -import com.taobao.rigel.rap.common.NumberUtils; -import com.taobao.rigel.rap.common.Patterns; -import com.taobao.rigel.rap.common.StringUtils; import com.taobao.rigel.rap.mock.service.MockMgr; import com.taobao.rigel.rap.project.bo.Action; import com.taobao.rigel.rap.project.bo.Parameter; @@ -26,6 +22,8 @@ public class MockMgrImpl implements MockMgr { private ProjectDao projectDao; private ProjectMgr projectMgr; + private int uid = 10000; + private final String ERROR_PATTERN = "{\"isOk\":false,\"msg\":\"路径为空,请查看是否接口未填写URL.\"}"; public ProjectMgr getProjectMgr() { return projectMgr; @@ -34,9 +32,28 @@ public ProjectMgr getProjectMgr() { public void setProjectMgr(ProjectMgr projectMgr) { this.projectMgr = projectMgr; } - + private Map> requestParams; + private boolean isPatternLegal(String pattern) { + if (pattern == null || pattern.isEmpty()) { + return false; + } + + String path = pattern; + if (path.indexOf("/") == 0) { + path = path.substring(1); + } + if (path.contains("?")) { + path = path.substring(0, path.indexOf("?")); + } + if (path.isEmpty()) { + return false; + } + + return true; + } + /** * random seed */ @@ -60,16 +77,17 @@ public void setProjectDao(ProjectDao projectDao) { @Override public String generateData(int projectId, String pattern, Map options) throws UnsupportedEncodingException { + + if (!isPatternLegal(pattern)) { + return ERROR_PATTERN; + } + _num = 1; String originalPattern = pattern; - // System.out.println("pattern before processed:" + pattern); if (pattern.contains("?")) { pattern = pattern.substring(0, pattern.indexOf("?")); } - if (pattern.charAt(0) == '/') { - pattern = pattern.substring(1); - } - // System.out.println("pattern processed:" + pattern); + List aList = projectMgr .getMatchedActionList(projectId, pattern); if (aList.size() == 0) @@ -141,26 +159,55 @@ public String generateRuleData(int projectId, String pattern, return MockjsRunner.renderMockjsRule(result); } + public String generateRuleData(int actionId) throws UnsupportedEncodingException { + String result = generateRule(actionId, null, null); + return MockjsRunner.renderMockjsRule(result); + } + @Override public String generateRule(int projectId, String pattern, - Map options) throws UnsupportedEncodingException { - String originalPattern = pattern; - _num = 1; - // System.out.println("pattern before processed:" + pattern); - if (pattern.contains("?")) { - pattern = pattern.substring(0, pattern.indexOf("?")); - } - if (pattern.charAt(0) == '/') { - pattern = pattern.substring(1); - } - // System.out.println("pattern processed:" + pattern); - List aList = projectMgr - .getMatchedActionList(projectId, pattern); - if (aList.size() == 0) { - return "{\"isOk\":false, \"errMsg\":\"no matched action\"}"; - } - - Action action = actionPick(aList, originalPattern, options); + Map options) throws UnsupportedEncodingException { + if (!isPatternLegal(pattern)) { + return ERROR_PATTERN; + } + String method = options.get("method").toString(); + String originalPattern = pattern; + int actionId = 0; + Action action; + + if (pattern == null && options == null) { + actionId = projectId; + } + _num = 1; + + if (actionId > 0) { // from OPenAPI, invoked by params(id, null, null) + action = projectMgr.getAction(actionId); + } else { + if (pattern.contains("?")) { + pattern = pattern.substring(0, pattern.indexOf("?")); + } + if (pattern.isEmpty()) { + return "{\"isOk\":false, \"errMsg\":\"pattern is empty. 路径为空,请检查RAP文档中的请求链接是否正确填写。\"}"; + } + List aList = projectMgr + .getMatchedActionList(projectId, pattern); + if (aList.size() == 0) { + return "{\"isOk\":false, \"errMsg\":\"no matched action\"}"; + } + + action = actionPick(aList, originalPattern, options); + if (action == null) { + return "{\"isOk\":false, \"errMsg\":\"no matched action\"}"; + } + + if (action.getDisableCache() == 0) { + String ruleCache = CacheUtils.getRuleCache(action, originalPattern); + if (ruleCache != null) { + return ruleCache; + } + } + + } String desc = action.getDescription(); Set pList = action.getResponseParameterList(); @@ -216,13 +263,46 @@ public String generateRule(int projectId, String pattern, } json.append(right); String result = json.toString(); - return resultFilter(result); + result = resultFilter(result); + CacheUtils.setRuleCache(action.getId(), result); + return result; } private Action actionPick(List actionList, String pattern, Map options) throws UnsupportedEncodingException { + + + List filteredActionList = new ArrayList(); + + // pattern match + for (Action action : actionList) { + if (URLUtils.isRelativeUrlExactlyMatch(pattern, action.getRequestUrl())) { + filteredActionList.add(action); + } + } + + if (!filteredActionList.isEmpty()) { + actionList = filteredActionList; + } + + if (actionList == null || actionList.isEmpty()) { + return null; + } + Action result = actionList.get(0); + + // request method match + for (Action action : actionList) { + if (options.get("method") != null && + action.getMethod().equals(options.get("method").toString())) { + result = action; + break; + } + } + requestParams = getUrlParameters(pattern); + + // schema match for (Action action : actionList) { Map> docActionParams = getUrlParameters(action .getRequestUrl()); @@ -270,6 +350,9 @@ public static Map> getUrlParameters(String url) String query = urlParts[1]; for (String param : query.split("&")) { String pair[] = param.split("="); + if (pair.length == 0) { + continue; + } String key = URLDecoder.decode(pair[0], "UTF-8"); String value = ""; if (pair.length > 1) { @@ -393,12 +476,14 @@ private void buildMockTemplate(StringBuilder json, Parameter para, int index) { int ARRAY_LENGTH = 1; if (para.getParameterList() == null - || para.getParameterList().size() == 0) { - json.append(para.getMockJSIdentifier() + ":" + || para.getParameterList().size() == 0 || para.hasMockJSData()) { + json.append(processMockValueWithParams(para.getMockJSIdentifier()) + + ":" + StringUtils.chineseToUnicode(mockjsValue(para, index))); } else { // object and array - json.append(para.getMockJSIdentifier() + ":"); + json.append(processMockValueWithParams(para.getMockJSIdentifier()) + + ":"); String left = "{", right = "}"; if (isArrayObject) { @@ -606,46 +691,129 @@ private String mockValue(Parameter para, int index) { } private String mockjsValue(Parameter para, int index) { - String[] tags = para.getMockDataTEMP().split(";"); + String mockData = para.getMockDataTEMP(); + String[] tags = mockData.split(";"); + if (mockData.contains("@mock=")) { + tags = new String[1]; + tags[0] = mockData.substring(mockData.indexOf("@mock=")); + } boolean escape = true; Map tagMap = new HashMap(); parseTags(tags, tagMap, true); String returnValue = "1"; String mockValue = tagMap.get("mock"); + if (mockValue == null && mockData.contains("@mock=")) { + mockValue = ""; + } if (mockValue == null || mockValue.isEmpty()) { - mockValue = tagMap.get("{mock}"); - escape = false; + String unescapeMockValue = tagMap.get("{mock}"); + if (unescapeMockValue != null && !unescapeMockValue.isEmpty()) { + escape = false; + mockValue = unescapeMockValue; + } } - - mockValue = processMockValueWithParams(para, mockValue); - + // default mock template generation + if (mockValue == null) { + if (para.getDataType().isEmpty()) { + return "1"; + } else if (para.getDataType().equals("number")) { + return NumberUtils.randomByFormat("xxxxx"); + } else if (para.getDataType().equals("boolean")) { + return new Boolean(NumberUtils.randomInt(10) > 5 ? true : false).toString(); + } else if (para.getDataType().equals("string")) { + Xeger generator = new Xeger("测试内容[0-9a-z]{4}"); + return "\"" + generator.generate() + "\""; + } else if (para.getDataType().equals("array")) { + return "[true, false]"; + } else if (para.getDataType().equals("array")) { + return "[]"; + } else if (para.getDataType().equals("object")) { + return "{}"; + } + } + + mockValue = processMockValueWithParams(mockValue); + if (mockValue != null && !mockValue.isEmpty()) { - if (mockValue.startsWith("[") && mockValue.endsWith("]")) { + if ((mockValue.startsWith("[") && mockValue.endsWith("]")) + || mockValue.startsWith("function")) { return mockValue; - } else if (para.getDataType().equals("number") - || para.getDataType().equals("boolean")) { + } else if (mockValue.startsWith("$order")) { + if (para.getDataType().contains("array")) { + return "[" + mockValue.substring(7, mockValue.length() - 1) + "]"; + } else { + StringBuilder orderCmdFunc = new StringBuilder(); + orderCmdFunc + .append("function() {") + .append(" var window = function(){return this;}();") + .append(" function geneVal(key) {") + .append(" var o = __rap__context__[key];") + .append(" var arr = o.arr;") + .append(" return arr[o.index++ % arr.length];") + .append(" }") + .append(" if (!window.__rap__context__) {") + .append(" window.__rap__context__ = {};") + .append(" }") + .append(" var orderCmd = \"" + StringUtils.escapeInJ(mockValue) + "\";") + .append(" var orderArr = eval('[' + orderCmd.substring(7, orderCmd.length - 1) + ']');") + .append(" var key = '" + (uid++) + "';") + .append(" if (!__rap__context__[key]) {") + .append(" __rap__context__[key] = {") + .append(" arr : orderArr,") + .append(" index : 0") + .append(" };") + .append(" }") + .append(" return geneVal(key);") + .append("}"); + + return orderCmdFunc.toString(); + } + } else if (mockValue.startsWith("@order")) { + return "\"" + StringUtils.escapeInJ(mockValue) + "\""; + } else if ((para.getDataType().equals("number") + || para.getDataType().equals("boolean")) + && !mockValue.startsWith("@")) { return mockValue; + } else if ((para.getDataType().equals("array") + || para.getDataType().equals("array") + || para.getDataType().equals("array"))) { + String result = mockValue; + if (para.getDataType().equals("array") + && !result.startsWith("\"") && !result.startsWith("'")) { + result = "\"" + result + "\""; + } + return "[" + result + "]"; } else { if (escape) { mockValue = StringUtils.escapeInJ(mockValue); } - return "\"" + mockValue + "\""; - } + if (mockValue.startsWith("\\\"") && mockValue.endsWith("\\\"")) { + return mockValue.substring(1, mockValue.length() - 2) + "\""; + } else if (!escape) { + return mockValue; + } else { + return "\"" + mockValue + "\""; + } + } + } else if (mockValue != null && mockValue.isEmpty() + && para.getDataType().equals("string")) { + return "\"\""; } else if (para.getDataType().equals("array")) { return "[\"string1\", \"string2\", \"string3\", \"string4\", \"string5\"]"; } else if (para.getDataType().equals("array")) { return "[1, 2, 3, 4, 5]"; - } + } return returnValue; } - - private String processMockValueWithParams(Parameter para, String mockValue) { - + private String processMockValueWithParams(String mockValue) { + Pattern p = Pattern.compile(Patterns.MOCK_TEMPLATE_PATTERN); - if (mockValue == null) mockValue = ""; + if (mockValue == null) { + mockValue = ""; + } Matcher matcher = p.matcher(mockValue); while (matcher.find()) { int c = matcher.groupCount(); @@ -654,7 +822,8 @@ private String processMockValueWithParams(Parameter para, String mockValue) { String key = matcher.group(1); String value = matcher.group(2); List param = requestParams.get(key); - String realValue = (param != null && param.size() > 0) ? param.get(0) : null; + String realValue = (param != null && param.size() > 0) ? param + .get(0) : null; if (realValue != null && !realValue.isEmpty()) { mockValue = mockValue.replace(toBeReplaced, realValue); } else { diff --git a/src/com/taobao/rigel/rap/mock/web/action/MockAction.java b/src/com/taobao/rigel/rap/mock/web/action/MockAction.java index 90f647538..cfdbf32ee 100644 --- a/src/com/taobao/rigel/rap/mock/web/action/MockAction.java +++ b/src/com/taobao/rigel/rap/mock/web/action/MockAction.java @@ -6,13 +6,20 @@ import java.util.List; import java.util.Map; +import com.google.gson.Gson; import com.taobao.rigel.rap.common.ActionBase; +import com.taobao.rigel.rap.common.SystemVisitorLog; import com.taobao.rigel.rap.mock.service.MockMgr; import com.taobao.rigel.rap.project.bo.Action; import com.taobao.rigel.rap.project.bo.Module; import com.taobao.rigel.rap.project.bo.Page; import com.taobao.rigel.rap.project.bo.Project; import com.taobao.rigel.rap.project.service.ProjectMgr; +import org.apache.logging.log4j.LogManager; +import org.apache.struts2.ServletActionContext; + +import javax.servlet.http.HttpServletRequest; + public class MockAction extends ActionBase { @@ -24,13 +31,19 @@ public class MockAction extends ActionBase { private int projectId; private String content; private String callback; + private boolean enable = true; private String _c; private ProjectMgr projectMgr; private List urlList; - + private boolean seajs; + private String mode; + private static final org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger(MockAction.class.getName()); public List getUrlList() { return urlList; } + private String getMethod() { + return ServletActionContext.getRequest().getMethod(); + } public void setUrlList(List urlList) { this.urlList = urlList; @@ -40,6 +53,34 @@ public ProjectMgr getProjectMgr() { return projectMgr; } + public int getProjectId() { + return projectId; + } + + public boolean isEnable() { + return enable; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + + public void setSeajs(boolean seajs) { + this.seajs = seajs; + } + + public boolean isSeajs() { + return seajs; + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + public void setProjectMgr(ProjectMgr projectMgr) { this.projectMgr = projectMgr; } @@ -112,6 +153,8 @@ public void setPattern(String pattern) { } public String createData() throws UnsupportedEncodingException { + boolean isJSON = false; + SystemVisitorLog.mock(id, "createData", pattern, getCurAccount(), projectMgr); Map options = new HashMap(); String _c = get_c(); String result = mockMgr.generateData(id, pattern, options); @@ -125,14 +168,23 @@ public String createData() throws UnsupportedEncodingException { } else if (_c != null && !_c.isEmpty()) { setContent(_c + "(" + result + ")"); } else { + isJSON = true; setContent(result); } - return SUCCESS; + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } } public String createRule() throws UnsupportedEncodingException { + boolean isJSON = false; + SystemVisitorLog.mock(id, "createRule", pattern, getCurAccount(), projectMgr); Map options = new HashMap(); String _c = get_c(); + options.put("method", getMethod()); + String result = mockMgr.generateRule(id, pattern, options); if (options.get("callback") != null) { _c = (String) options.get("callback"); @@ -143,9 +195,39 @@ public String createRule() throws UnsupportedEncodingException { } else if (_c != null && !_c.isEmpty()) { setContent(_c + "(" + result + ")"); } else { + isJSON = true; setContent(result); } - return SUCCESS; + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String createRuleByActionData() throws UnsupportedEncodingException { + boolean isJSON = false; + SystemVisitorLog.mock(id, "createRuleByActionData", pattern, getCurAccount(), projectMgr); + Map options = new HashMap(); + String _c = get_c(); + String result = mockMgr.generateRule(id, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } } public String modify() { @@ -159,8 +241,37 @@ public String reset() { } public String createPluginScript() { + SystemVisitorLog.mock(id, "createPluginScript", pattern, getCurAccount(), projectMgr); + Map _circleRefProtector = new HashMap(); List list = new ArrayList(); Project p = projectMgr.getProject(projectId); + + loadWhiteList(p, list, _circleRefProtector); + urlList = list; + return SUCCESS; + } + + public String getWhiteList() { + Map _circleRefProtector = new HashMap(); + List list = new ArrayList(); + Project p = projectMgr.getProject(projectId); + + loadWhiteList(p, list, _circleRefProtector); + urlList = list; + Gson g = new Gson(); + String json = g.toJson(urlList); + setJson(json); + + return SUCCESS; + } + + private void loadWhiteList(Project p, List list, Map map) { + // prevent circle reference + if (p == null || map.get(p.getId() + "") != null) { + return; + } else { + map.put(p.getId() + "", true); + } if (p != null) { for (Module m : p.getModuleList()) { for (Page page : m.getPageList()) { @@ -170,13 +281,25 @@ public String createPluginScript() { } } } - urlList = list; - return SUCCESS; + + String relatedIds = p.getRelatedIds(); + if (relatedIds != null && !relatedIds.isEmpty()) { + String[] relatedIdsArr = relatedIds.split(","); + for (String relatedId : relatedIdsArr) { + int rId = Integer.parseInt(relatedId); + Project rP = projectMgr.getProject(rId); + if (rP != null && rP.getId() > 0) + loadWhiteList(rP, list, map); + } + } } public String createMockjsData() throws UnsupportedEncodingException { + boolean isJSON = false; + SystemVisitorLog.mock(id, "createMockjsData", pattern, getCurAccount(), projectMgr); String _c = get_c(); Map options = new HashMap(); + options.put("method", getMethod()); String result = mockMgr.generateRuleData(id, pattern, options); if (options.get("callback") != null) { _c = (String) options.get("callback"); @@ -187,8 +310,14 @@ public String createMockjsData() throws UnsupportedEncodingException { } else if (_c != null && !_c.isEmpty()) { setContent(_c + "(" + result + ")"); } else { + isJSON = true; setContent(result); } - return SUCCESS; + + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } } } diff --git a/src/com/taobao/rigel/rap/mock/web/action/struts.xml b/src/com/taobao/rigel/rap/mock/web/action/struts.xml index 83406857d..be0273dd8 100644 --- a/src/com/taobao/rigel/rap/mock/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/mock/web/action/struts.xml @@ -25,6 +25,10 @@ /bcom/contentWithoutEscape.cb.vm + + application/json + /bcom/contentWithoutEscape.cb.vm + /bcom/contentWithoutEscape.cb.vm + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + @@ -41,16 +60,25 @@ /bcom/contentWithoutEscape.cb.vm - + + application/json + /bcom/contentWithoutEscape.cb.vm + - + text/javascript - /mock/createPluginScript.vm + /mock/createPluginScript.vm + + + /bcom/json.cb.vm + + \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/organization/web/action/GroupAction.java b/src/com/taobao/rigel/rap/organization/web/action/GroupAction.java index 27bdbc461..5cef38d29 100644 --- a/src/com/taobao/rigel/rap/organization/web/action/GroupAction.java +++ b/src/com/taobao/rigel/rap/organization/web/action/GroupAction.java @@ -19,15 +19,11 @@ public class GroupAction extends ActionBase { private OrganizationMgr organizationMgr; private ProjectMgr projectMgr; private int id; - - public int getId() { return id; } - - public void setId(int id) { this.id = id; } @@ -81,9 +77,11 @@ public String all() { .getProjectListByGroup(groupModel.getId()); List> projects = new ArrayList>(); for (Project projectModel : projectModelList) { - if (getCurUser().isUserInRole("admin") || getCurUser().getId() == projectModel.getUser().getId()) { + if (getCurUser().isUserInRole("admin") + || getAccountMgr().canUserManageProject( + getCurUser().getId(), projectModel.getId())) { projectModel.setIsManagable(true); - } + } Map project = new HashMap(); project.put("id", projectModel.getId()); project.put("name", projectModel.getName()); @@ -91,6 +89,7 @@ public String all() { project.put("status", projectModel.getLastUpdateStr()); project.put("accounts", projectModel.getMemberAccountListStr()); project.put("isManagable", projectModel.getIsManagable()); + project.put("creator", projectModel.getUser().getUserBaseInfo()); projects.add(project); } group.put("projects", projects); @@ -103,6 +102,24 @@ public String all() { return SUCCESS; } + public String groups() { + Gson gson = new Gson(); + Map result = new HashMap(); + List> groups = new ArrayList>(); + List groupModels = organizationMgr.getGroupList(productLineId); + for (Group groupModel : groupModels) { + Map group = new HashMap(); + group.put("id", groupModel.getId()); + group.put("name", groupModel.getName()); + groups.add(group); + } + + result.put("groups", groups); + + setJson(gson.toJson(result)); + return SUCCESS; + } + public String create() { Gson gson = new Gson(); Group group = new Group(); diff --git a/src/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java b/src/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java index 54bc422f2..aecfe1ecc 100644 --- a/src/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java +++ b/src/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java @@ -62,7 +62,12 @@ public String myHome() { } public String index() { - return SUCCESS; + if (isUserLogined()) { + return SUCCESS; + } else { + return "public"; + } + } public String group() { @@ -73,7 +78,8 @@ public String group() { public String productline() { Corporation c = organizationMgr.getCorporation(id); if (c != null) { - ContextManager.getSession().put(ContextManager.KEY_CORP_NAME, c.getName()); + ContextManager.getSession().put(ContextManager.KEY_CORP_NAME, + c.getName()); } return SUCCESS; } @@ -83,13 +89,15 @@ public String projects() { return LOGIN; Gson gson = new Gson(); List> projects = new ArrayList>(); - long totalRecNum = projectMgr.getProjectListNum(getCurUser()); + // long totalRecNum = projectMgr.getProjectListNum(getCurUser()); List projectList = projectMgr.getProjectList(getCurUser(), 1, - (int) totalRecNum); + Integer.MAX_VALUE); for (Project p : projectList) { - if (getCurUser().isUserInRole("admin") || getCurUser().getId() == p.getUser().getId()) { + if (getCurUser().isUserInRole("admin") + || getAccountMgr().canUserManageProject( + getCurUser().getId(), p.getId())) { p.setIsManagable(true); - } + } Map map = new HashMap(); map.put("id", p.getId()); map.put("name", p.getName()); @@ -97,6 +105,8 @@ public String projects() { map.put("status", p.getLastUpdateStr()); map.put("accounts", p.getMemberAccountListStr()); map.put("isManagable", p.getIsManagable()); + map.put("creator", p.getUser().getUserBaseInfo()); + map.put("related", p.getUser().getId() != getCurUserId()); projects.add(map); } StringBuilder json = new StringBuilder(); diff --git a/src/com/taobao/rigel/rap/organization/web/action/struts.xml b/src/com/taobao/rigel/rap/organization/web/action/struts.xml index f5a2503d9..e9ddf414e 100644 --- a/src/com/taobao/rigel/rap/organization/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/organization/web/action/struts.xml @@ -9,6 +9,7 @@ /org/home/index.vm + /platform/home.vm @@ -50,6 +51,10 @@ /bcom/json.cb.vm + + /bcom/json.cb.vm + + /bcom/json.cb.vm diff --git a/src/com/taobao/rigel/rap/platform/applicationContext.xml b/src/com/taobao/rigel/rap/platform/applicationContext.xml new file mode 100644 index 000000000..03e17f909 --- /dev/null +++ b/src/com/taobao/rigel/rap/platform/applicationContext.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/platform/dao/DataDao.java b/src/com/taobao/rigel/rap/platform/dao/DataDao.java new file mode 100644 index 000000000..8ac1b8936 --- /dev/null +++ b/src/com/taobao/rigel/rap/platform/dao/DataDao.java @@ -0,0 +1,19 @@ +package com.taobao.rigel.rap.platform.dao; + +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-5. + */ +public interface DataDao { + + List> getUserTrendByMonth(); + + List> getProjectTrendByMonth(); + + List> getCheckInTrendByMonth(); + + List> getActionNumByTeam(); + +} diff --git a/src/com/taobao/rigel/rap/platform/dao/impl/DataDaoImpl.java b/src/com/taobao/rigel/rap/platform/dao/impl/DataDaoImpl.java new file mode 100644 index 000000000..f559ac713 --- /dev/null +++ b/src/com/taobao/rigel/rap/platform/dao/impl/DataDaoImpl.java @@ -0,0 +1,130 @@ +package com.taobao.rigel.rap.platform.dao.impl; + +import com.taobao.rigel.rap.platform.dao.DataDao; +import org.hibernate.Query; +import org.springframework.orm.hibernate3.support.HibernateDaoSupport; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-5. + */ +public class DataDaoImpl extends HibernateDaoSupport implements DataDao { + @Override + public List> getUserTrendByMonth() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT MONTH(create_date) AS month, COUNT(id) as num, create_date ") + .append("FROM tb_user ") + .append("WHERE create_date BETWEEN DATE_ADD(NOW(), INTERVAL -1 YEAR) AND NOW() ") + .append("GROUP BY MONTH(create_date) ") + .append("ORDER BY create_date"); + Query query = getSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("num", row[1]); + map.put("date", row[2]); + result.add(map); + } + + Object count = getSession().createSQLQuery("SELECT COUNT(*) FROM tb_user WHERE create_date < DATE_ADD(NOW(), INTERVAL -1 YEAR)") + .uniqueResult(); + Map mapCount = new HashMap(); + mapCount.put("startValue", count); + result.add(mapCount); + + + return result; + } + + @Override + public List> getProjectTrendByMonth() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT MONTH(create_date) AS month, COUNT(id) as num, create_date ") + .append("FROM tb_project ") + .append("WHERE create_date BETWEEN DATE_ADD(NOW(), INTERVAL -1 YEAR) AND NOW() ") + .append("GROUP BY MONTH(create_date) ") + .append("ORDER BY create_date"); + Query query = getSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("num", row[1]); + map.put("date", row[2]); + result.add(map); + } + + Object count = getSession().createSQLQuery("SELECT COUNT(*) FROM tb_project WHERE create_date < DATE_ADD(NOW(), INTERVAL -1 YEAR)") + .uniqueResult(); + Map mapCount = new HashMap(); + mapCount.put("startValue", count); + result.add(mapCount); + + return result; + } + + @Override + public List> getCheckInTrendByMonth() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT MONTH(create_date) AS month, COUNT(id) as num, create_date ") + .append("FROM tb_check_in ") + .append("WHERE create_date BETWEEN DATE_ADD(NOW(), INTERVAL -1 YEAR) AND NOW() ") + .append("GROUP BY MONTH(create_date) ") + .append("ORDER BY create_date"); + Query query = getSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("num", row[1]); + map.put("date", row[2]); + result.add(map); + } + + Object count = getSession().createSQLQuery("SELECT COUNT(*) FROM tb_check_in WHERE create_date < DATE_ADD(NOW(), INTERVAL -1 YEAR)") + .uniqueResult(); + Map mapCount = new HashMap(); + mapCount.put("startValue", count); + result.add(mapCount); + + return result; + } + + @Override + public List> getActionNumByTeam() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT c.name, COUNT(a.id) as num ") + .append("FROM tb_action a ") + .append("JOIN tb_action_and_page ap ON ap.action_id = a.id ") + .append("JOIN tb_page p ON p.id = ap.page_id ") + .append("JOIN tb_module m ON m.id = p.module_id ") + .append("JOIN tb_project pr ON pr.id = m.project_id ") + .append("JOIN tb_group g ON g.id = pr.group_id ") + .append("JOIN tb_production_line pl ON pl.id = g.production_line_id ") + .append("JOIN tb_corporation c ON c.id = pl.corporation_id ") + .append("GROUP BY c.name ") + .append("ORDER BY COUNT(a.id) DESC "); + + + Query query = getSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("name", row[0]); + map.put("num", row[1]); + result.add(map); + } + + return result; + } +} diff --git a/src/com/taobao/rigel/rap/platform/service/DataMgr.java b/src/com/taobao/rigel/rap/platform/service/DataMgr.java new file mode 100644 index 000000000..b5f2072bf --- /dev/null +++ b/src/com/taobao/rigel/rap/platform/service/DataMgr.java @@ -0,0 +1,20 @@ +package com.taobao.rigel.rap.platform.service; + +import java.util.List; +import java.util.Map; + +/** + * Created by mashengbo on 14-9-5. + */ +public interface DataMgr { + + List> getUserTrendByMonth(); + + List> getProjectTrendByMonth(); + + List> getCheckInTrendByMonth(); + + List> getActionNumByTeam(); + + List> getMockNumByProject(); +} diff --git a/src/com/taobao/rigel/rap/platform/service/impl/DataMgrImpl.java b/src/com/taobao/rigel/rap/platform/service/impl/DataMgrImpl.java new file mode 100644 index 000000000..bfdeca7da --- /dev/null +++ b/src/com/taobao/rigel/rap/platform/service/impl/DataMgrImpl.java @@ -0,0 +1,70 @@ +package com.taobao.rigel.rap.platform.service.impl; + +import com.taobao.rigel.rap.platform.dao.DataDao; +import com.taobao.rigel.rap.platform.service.DataMgr; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-5. + */ +public class DataMgrImpl implements DataMgr { + private DataDao dataDao; + private ProjectMgr projectMgr; + + public void setDataDao(DataDao dataDao) { + this.dataDao = dataDao; + } + + public DataDao getDataDao() { + return dataDao; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + @Override + public List> getUserTrendByMonth() { + return dataDao.getUserTrendByMonth(); + } + + @Override + public List> getProjectTrendByMonth() { + return dataDao.getProjectTrendByMonth(); + } + + @Override + public List> getCheckInTrendByMonth() { + return dataDao.getCheckInTrendByMonth(); + } + + @Override + public List> getActionNumByTeam() { + return dataDao.getActionNumByTeam(); + } + + @Override + public List> getMockNumByProject() { + List list = projectMgr.selectMockNumTopNProjectList(5); + List> results = new ArrayList>(); + for (Project p : list) { + Map row = new HashMap(); + row.put("id", p.getId()); + row.put("name", p.getName()); + row.put("mockNum", p.getMockNum()); + results.add(row); + } + return results; + } + +} diff --git a/src/com/taobao/rigel/rap/platform/web/action/PlatformAction.java b/src/com/taobao/rigel/rap/platform/web/action/PlatformAction.java index 450c696da..1eed1471c 100644 --- a/src/com/taobao/rigel/rap/platform/web/action/PlatformAction.java +++ b/src/com/taobao/rigel/rap/platform/web/action/PlatformAction.java @@ -4,16 +4,109 @@ import java.io.IOException; import java.io.InputStreamReader; +import com.google.gson.Gson; +import com.opensymphony.xwork2.ActionContext; +import com.taobao.rigel.rap.common.Item; +import com.taobao.rigel.rap.common.SystemVisitorLog; +import com.taobao.rigel.rap.platform.service.DataMgr; +import com.taobao.rigel.rap.project.service.ProjectMgr; import org.apache.commons.io.IOUtils; import com.taobao.rigel.rap.common.ActionBase; import com.taobao.rigel.rap.common.SystemConstant; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + public class PlatformAction extends ActionBase { + private Gson gson = new Gson(); + + private long time; + + public void setTime(long time) { + this.time = time; + } + + private static final Logger logger = LogManager.getFormatterLogger(PlatformAction.class.getName()); private static final long serialVersionUID = 1L; - private String text; + private Map>> trends = new HashMap>>(); + + public Map>> getTrends() { + return trends; + } + + private Map>> statistics = new HashMap>>(); + + public Map>> getStatistics() { + return statistics; + } + + public String getTrendsJSON() { + return gson.toJson(getTrends()); + } + + public String getStatisticsJSON() { + return gson.toJson(getStatistics()); + } + + public String getRealtimeJSON() { + return gson.toJson(SystemVisitorLog.getRealtimeMap(null)); + } + + public String getRealtimeJSONByTime(long time) { + return gson.toJson(SystemVisitorLog.getRealtimeMap(time)); + } + + + + private int tabIndex; + + public int getTabIndex() { + return tabIndex; + } + + public void setTabIndex(int tabIndex) { + this.tabIndex = tabIndex; + } + + private ProjectMgr projectMgr; + private List modelLog = new ArrayList(); + + private Map modelLogMap = new HashMap(); + + public Map getModelLogMap() { + return modelLogMap; + } + + public List getModelLog() { + return modelLog; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + private DataMgr dataMgr; + + public DataMgr getDataMgr() { + return dataMgr; + } + + public void setDataMgr(DataMgr dataMgr) { + this.dataMgr = dataMgr; + } + + private String text; public String getText() { return text; @@ -27,30 +120,52 @@ public String home() { return SUCCESS; } - public String document() { + public String test() { return SUCCESS; } - public String about() { - return SUCCESS; - } + public String log() { + // statistics for RAP models + modelLog.add(new Item("用户数", new Long(getAccountMgr().getUserNum()).toString())); + modelLog.add(new Item("项目数", new Long(projectMgr.getProjectNum()).toString())); + modelLog.add(new Item("接口数", new Long(projectMgr.getActionNum()).toString())); + //modelLog.add(new Item("TAB数", new Long(projectMgr.getModuleNum()).toString())); + //modelLog.add(new Item("页面数", new Long(projectMgr.getPageNum()).toString())); + //modelLog.add(new Item("参数数", new Long(projectMgr.getParametertNum()).toString())); + modelLog.add(new Item("文档提交数", new Long(projectMgr.getCheckInNum()).toString())); + modelLog.add(new Item("MOCK服务调用次数", new Long(projectMgr.getMockNumInTotal()).toString(), "该信息自2014年10月底开始记录")); - public String status() { - return SUCCESS; - } - - public String test() { - return SUCCESS; - } + for (Item item : modelLog) { + modelLogMap.put(item.getKey(), item); + } - public String help() throws IOException { - FileInputStream inputStream = new FileInputStream(SystemConstant.README_PATH); - InputStreamReader reader = new InputStreamReader(inputStream, "UTF8"); - try { - text = IOUtils.toString(reader); - } finally { - inputStream.close(); - } - return SUCCESS; - } + // trends data + trends.put("user", dataMgr.getUserTrendByMonth()); + trends.put("project", dataMgr.getProjectTrendByMonth()); + trends.put("checkIn", dataMgr.getCheckInTrendByMonth()); + + + + // statistics data + statistics.put("actionNumByTeam", dataMgr.getActionNumByTeam()); + statistics.put("mockNumByProject", dataMgr.getMockNumByProject()); + statistics.put("mockNumByProjectToday", SystemVisitorLog.getMockNumByProjectToday(projectMgr)); + + return SUCCESS; + } + + public String realtimeUpdate() { + setJson(getRealtimeJSONByTime(time)); + return SUCCESS; + } + + public String monitor() { + Map logs = new HashMap(); + logs.put("ipLog", SystemVisitorLog.getAllIpLog()); + logs.put("userLog", SystemVisitorLog.getAllUserLog()); + logs.put("mockLog", SystemVisitorLog.getMockMapList()); + Gson gson = new Gson(); + setJson(gson.toJson(logs)); + return SUCCESS; + } } diff --git a/src/com/taobao/rigel/rap/platform/web/action/struts.xml b/src/com/taobao/rigel/rap/platform/web/action/struts.xml index f2343dd0f..6759ba5b5 100644 --- a/src/com/taobao/rigel/rap/platform/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/platform/web/action/struts.xml @@ -6,21 +6,18 @@ /platform/home.vm - - - /platform/document.vm - - - /platform/about.vm - - - /platform/status.vm - - - /platform/help.vm /platform/test.vm + + /platform/log.vm + + + /platform/monitor.vm + + + /bcom/json.cb.vm + diff --git a/src/com/taobao/rigel/rap/project/applicationContext.xml b/src/com/taobao/rigel/rap/project/applicationContext.xml index 9809c7532..ef6259689 100644 --- a/src/com/taobao/rigel/rap/project/applicationContext.xml +++ b/src/com/taobao/rigel/rap/project/applicationContext.xml @@ -1,11 +1,14 @@ - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/project/bo/Action.java b/src/com/taobao/rigel/rap/project/bo/Action.java index 3869a2f66..eb33b02ab 100644 --- a/src/com/taobao/rigel/rap/project/bo/Action.java +++ b/src/com/taobao/rigel/rap/project/bo/Action.java @@ -6,6 +6,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import com.taobao.rigel.rap.common.StringUtils; @@ -13,18 +14,30 @@ public class Action implements java.io.Serializable { private static final long serialVersionUID = 1L; + + public enum TYPE {REQUEST, RESPONSE}; - private int id; + private long id; - public int getId() { + public long getId() { return id; } - public void setId(int id) { + public void setId(long id) { this.id = id; } - private String name; + private int disableCache; + + public int getDisableCache() { + return disableCache; + } + + public void setDisableCache(int disableCache) { + this.disableCache = disableCache; + } + + private String name; public String getName() { return name; @@ -56,6 +69,18 @@ public void setRequestType(String requestType) { this.requestType = requestType; } + public String getMethod() { + if (this.requestType.equals("2")) { + return "POST"; + } else if (this.requestType.equals("3")) { + return "PUT"; + } else if (this.requestType.equals("4")) { + return "DELETE"; + } else { + return "GET"; // in default + } + } + private String requestUrl; public String getRequestUrl() { @@ -262,5 +287,20 @@ public String getRequestUrlRel() { } return url; } + + public static List loadList(List> result) { + List list = new ArrayList(); + for (Map row : result) { + Action obj = new Action(); + obj.setDescription((String)row.get("description")); + obj.setId((Integer)row.get("id")); + obj.setName((String)row.get("name")); + obj.setRemarks((String)row.get("remarks")); + obj.setRequestType((String)row.get("request_type")); + obj.setRequestUrl((String)row.get("request_url")); + list.add(obj); + } + return list; + } } diff --git a/src/com/taobao/rigel/rap/project/bo/Module.java b/src/com/taobao/rigel/rap/project/bo/Module.java index 199d72e97..ba3f47190 100644 --- a/src/com/taobao/rigel/rap/project/bo/Module.java +++ b/src/com/taobao/rigel/rap/project/bo/Module.java @@ -112,7 +112,7 @@ public String toString() { return stringBuilder.toString(); } - public String toString(Project.toStringType type) { + public String toString(Project.TO_STRING_TYPE type) { StringBuilder stringBuilder = new StringBuilder(); diff --git a/src/com/taobao/rigel/rap/project/bo/Page.java b/src/com/taobao/rigel/rap/project/bo/Page.java index 5c46216cd..4aa49175e 100644 --- a/src/com/taobao/rigel/rap/project/bo/Page.java +++ b/src/com/taobao/rigel/rap/project/bo/Page.java @@ -114,13 +114,13 @@ public String toString() { return stringBuilder.toString(); } - public String toString(Project.toStringType type) { + public String toString(Project.TO_STRING_TYPE type) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("{\"id\":" + getId() + ","); stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\""); - if (type == Project.toStringType.TO_PAGE) { + if (type == Project.TO_STRING_TYPE.TO_PAGE) { stringBuilder.append("}"); } else { stringBuilder.append(",\"actionList\":"); diff --git a/src/com/taobao/rigel/rap/project/bo/Parameter.java b/src/com/taobao/rigel/rap/project/bo/Parameter.java index 7c3bfc19b..4c7f19f40 100644 --- a/src/com/taobao/rigel/rap/project/bo/Parameter.java +++ b/src/com/taobao/rigel/rap/project/bo/Parameter.java @@ -65,7 +65,7 @@ public String getIdentifier() { public String getMockIdentifier() { String rv = ""; if (identifier == null || identifier.isEmpty()) { - return "emptyIdentifier"; + return "\"emptyIdentifier\""; } rv = identifier; @@ -77,11 +77,27 @@ public String getMockIdentifier() { } return "\"" + rv + "\""; } - + + public String getIdentifierWithoutMockjsRule() { + String rv; + if (identifier == null || identifier.isEmpty()) { + return "emptyIdentifier"; + } + + rv = identifier; + if (rv != null && !rv.isEmpty()) { + int index = rv.indexOf("|"); + if (index > -1) { + rv = rv.substring(0, index); + } + } + return rv; + } + public String getMockJSIdentifier() { String rv = ""; if (identifier == null || identifier.isEmpty()) { - return "emptyIdentifier"; + return "\"emptyIdentifier\""; } rv = identifier; return "\"" + rv + "\""; @@ -94,6 +110,9 @@ public void setIdentifier(String identifier) { private String dataType; public String getDataType() { + if (this.dataType == null || this.dataType.trim().isEmpty()) { + return ""; + } return dataType; } @@ -208,4 +227,33 @@ public String toString() { return stringBuilder.toString(); } + public String getRemarkWithoutMockjsRule() { + if (remark != null && remark.contains("@mock=")) { + return remark.substring(0, remark.indexOf("@mock=")); + } else { + return remark; + } + } + + public String getMockJsRules() { + if (remark == null || remark.isEmpty() || (!remark.contains("@mock="))) { + return null; + } + return remark.substring(remark.indexOf("@mock=") + 6); + + } + + + public String getJSONSchemaDataType() { + if (dataType != null && dataType.contains("array")) { + return "array"; + } + return this.dataType; + } + + public boolean hasMockJSData() { + return this.getMockJsRules() != null; + } + + } diff --git a/src/com/taobao/rigel/rap/project/bo/Project.java b/src/com/taobao/rigel/rap/project/bo/Project.java index 68931e435..b9587be2a 100644 --- a/src/com/taobao/rigel/rap/project/bo/Project.java +++ b/src/com/taobao/rigel/rap/project/bo/Project.java @@ -33,8 +33,17 @@ public class Project implements java.io.Serializable { private int workspaceModeInt; private String relatedIds = ""; private int groupId; - - public int getGroupId() { + private int mockNum; + + public void setMockNum(int mockNum) { + this.mockNum = mockNum; + } + + public int getMockNum() { + return mockNum; + } + + public int getGroupId() { return groupId; } @@ -50,9 +59,9 @@ public void setRelatedIds(String relatedIds) { this.relatedIds = relatedIds; } - public enum toStringType {TO_MODULE, TO_PAGE, TO_ACTION, TO_PARAMETER}; + public enum TO_STRING_TYPE {TO_MODULE, TO_PAGE, TO_ACTION, TO_PARAMETER}; - public enum StageType {DESIGNING, DEVELOPING, DEBUGING}; + public enum STAGE_TYPE {DESIGNING, DEVELOPING, DEBUGING}; public int getWorkspaceModeInt() { return workspaceModeInt; @@ -214,7 +223,7 @@ public void setVersion(String version) { this.version = version; } - public String toString(toStringType type) { + public String toString(TO_STRING_TYPE type) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("{\"createDateStr\":\"" + getCreateDateStr() + "\","); stringBuilder.append("\"user\":" + getUser() + ","); @@ -336,7 +345,7 @@ public Page findPage(int pageId) { return null; } - public Action findAction(int actionId) { + public Action findAction(long actionId) { for (Module module : getModuleList()) { for (Page page : module.getPageList()) { for (Action action : page.getActionList()) { @@ -471,10 +480,10 @@ public void removeParameter(int id, Session session) { } } - public void addMember(User user) { + public boolean addMember(User user) { // if member added is the creator, ignore if (user.getId() == getUser().getId()) - return; + return false; // if member already exists, ignore boolean exist = false; for (User item : getUserList()) { @@ -482,10 +491,11 @@ public void addMember(User user) { exist = true; } } - if (exist) return; + if (exist) return false; // validation complete, add this user getUserList().add(user); user.getJoinedProjectList().add(this); + return true; } public void removeMember(User user) { @@ -497,4 +507,16 @@ public String getLastUpdateStr() { PrettyTime p = new PrettyTime(new Locale("zh")); return p.format(this.updateTime) + "更新"; } + + public List getAllAction() { + List list = new ArrayList(); + for (Module m : this.moduleList) { + for (Page p : m.getPageList()) { + for (Action a : p.getActionList()) { + list.add(a); + } + } + } + return list; + } } diff --git a/src/com/taobao/rigel/rap/project/dao/ProjectDao.java b/src/com/taobao/rigel/rap/project/dao/ProjectDao.java index 70b77be36..75628c02e 100644 --- a/src/com/taobao/rigel/rap/project/dao/ProjectDao.java +++ b/src/com/taobao/rigel/rap/project/dao/ProjectDao.java @@ -1,6 +1,7 @@ package com.taobao.rigel.rap.project.dao; import java.util.List; +import java.util.Map; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.project.bo.Action; @@ -34,7 +35,7 @@ public interface ProjectDao { * @return */ String updateProject(int id, String projectData, - String deletedObjectListData); + String deletedObjectListData, Map actionIdMap); /** * update project @@ -77,7 +78,7 @@ String updateProject(int id, String projectData, * @param id * @return */ - Action getAction(int id); + Action getAction(long id); /** * save project @@ -101,8 +102,8 @@ String updateProject(int id, String projectData, * @return */ List getMatchedActionList(int projectId, String pattern); - - /** + + /** * clear all mock data of objects in specified project * @param projectId project id * @return affected rows num @@ -123,4 +124,22 @@ String updateProject(int id, String projectData, * @return */ List search(String key); + + List getProjectList(); + + long getProjectListNum(); + + long getModuleNum(); + + long getPageNum(); + + long getActionNum(); + + long getParametertNum(); + + long getCheckInNum(); + + long getMockNumInTotal(); + + List selectMockNumTopNProjectList(int limit); } diff --git a/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java b/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java index 62d96777e..e86075618 100644 --- a/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java +++ b/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java @@ -2,8 +2,12 @@ import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import com.taobao.rigel.rap.common.CacheUtils; +import com.taobao.rigel.rap.common.URLUtils; import org.hibernate.ObjectNotFoundException; import org.hibernate.Query; import org.hibernate.Session; @@ -12,6 +16,7 @@ import com.google.gson.Gson; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.common.ArrayUtils; +import com.taobao.rigel.rap.common.StringUtils; import com.taobao.rigel.rap.project.bo.Action; import com.taobao.rigel.rap.project.bo.Module; import com.taobao.rigel.rap.project.bo.ObjectItem; @@ -22,19 +27,38 @@ public class ProjectDaoImpl extends HibernateDaoSupport implements ProjectDao { - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") @Override public List getProjectList(User user, int curPageNum, int pageSize) { - curPageNum = curPageNum <= 0 ? 1 : curPageNum; - String hqlByUser = "from Project as p left join fetch p.userList as u where p.user.id = :userId or u.id = :userId order by p.id desc"; - Query query = getSession().createQuery(hqlByUser).setLong("userId", - user.getId()); - query = query.setFirstResult(pageSize * (curPageNum - 1)); - query.setMaxResults(pageSize); - return query.list(); + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT project_id ") + .append("FROM tb_project_and_user ") + .append("WHERE user_id = :userId ") + .append("UNION ") + .append("SELECT id ") + .append("FROM tb_project ") + .append("WHERE user_id = :userId "); + Query query = getSession().createSQLQuery(sql.toString()).setLong("userId", + user.getId()); + + List list = query.list(); + List resultList = new ArrayList(); + for (Integer id : list) { + Project p = this.getProject(id); + if (p != null && p.getId() > 0) { + resultList.add(p); + } + } + return resultList; } + @Override + public List getProjectList() { + String hqlByUser = "from Project"; + Query query = getSession().createQuery(hqlByUser); + return query.list(); + } - @Override public int addProject(Project project) { Session session = getSession(); @@ -47,7 +71,7 @@ public int addProject(Project project) { session.save(project); project = (Project) session.load(Project.class, project.getId()); project.setProjectData(project - .toString(Project.toStringType.TO_PARAMETER)); + .toString(Project.TO_STRING_TYPE.TO_PARAMETER)); return project.getId(); } @@ -102,8 +126,9 @@ public Page getPage(int id) { return (Page) getSession().get(Page.class, id); } + @Override - public Action getAction(int id) { + public Action getAction(long id) { return (Action) getSession().get(Action.class, id); } @@ -120,7 +145,7 @@ public int saveProject(Project project) { @Override public String updateProject(int id, String projectData, - String deletedObjectListData) { + String deletedObjectListData, Map actionIdMap) { Session session = getSession(); // StringBuilder log = new StringBuilder(); Gson gson = new Gson(); @@ -165,10 +190,13 @@ public String updateProject(int id, String projectData, Action actionServer = projectServer.findAction(action .getId()); if (actionServer == null) { - addAction(session, page, action); + long oldActionId = action.getId(); + long createdActionId = addAction(session, page, action); + actionIdMap.put(oldActionId, createdActionId); continue; } actionServer.update(action); + CacheUtils.removeCacheByActionId(action.getId()); for (Parameter parameter : action.getRequestParameterList()) { Parameter parameterServer = projectServer .findParameter(parameter.getId(), true); @@ -238,16 +266,17 @@ private void addPage(Session session, Module module, Page page) { } } - private void addAction(Session session, Page page, Action action) { + private long addAction(Session session, Page page, Action action) { page = (Page) session.load(Page.class, page.getId()); page.addAction(action); - session.save(action); + long createdId = (Long)session.save(action); for (Parameter parameter : action.getRequestParameterList()) { addParameter(session, action, parameter, true); } for (Parameter parameter : action.getResponseParameterList()) { addParameter(session, action, parameter, false); } + return createdId; } private void addParameter(Session session, Action action, @@ -295,26 +324,123 @@ public long getProjectListNum(User user) { return list.get(0); } - @SuppressWarnings("unchecked") + @Override + public long getProjectListNum() { + String sql = "SELECT COUNT(*) FROM tb_project"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + + @Override + public long getModuleNum() { + String sql = "SELECT COUNT(*) FROM tb_module"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + + @Override + public long getPageNum() { + String sql = "SELECT COUNT(*) FROM tb_page"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + + @Override + public long getActionNum() { + String sql = "SELECT COUNT(*) FROM tb_action"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + + @Override + public long getMockNumInTotal() { + String sql = "SELECT SUM(mock_num) FROM tb_project"; + Query query = getSession().createSQLQuery(sql); + Object queryResult = query.uniqueResult(); + return queryResult != null ? Long.parseLong(queryResult.toString()) : 0; + } + + @Override + public long getParametertNum() { + String sql = "SELECT COUNT(*) FROM tb_parameter"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + + @Override + public long getCheckInNum() { + String sql = "SELECT COUNT(*) FROM tb_check_in"; + Query query = getSession().createSQLQuery(sql); + return Long.parseLong(query.uniqueResult().toString()); + } + @Override public List getMatchedActionList(int projectId, String pattern) { - StringBuilder sb = new StringBuilder(); - sb.append("SELECT a.id FROM tb_action a ") - .append("JOIN tb_action_and_page ap ON ap.action_id = a.id ") - .append("JOIN tb_page p ON p.id = ap.page_id ") - .append("JOIN tb_module m ON m.id = p.module_id ") - .append("WHERE LOCATE(:pattern, a.request_url) != 0 AND m.project_id = :projectId "); - - String sql = sb.toString(); - Query query = getSession().createSQLQuery(sql); - query.setString("pattern", pattern); - query.setInteger("projectId", projectId); - List list = query.list(); - List actionList = new ArrayList(); - for (int id : list) { - actionList.add(getAction(id)); + List list = getActionListOfProject(projectId); + List result = new ArrayList(); + for (Action action : list) { + String url = action.getRequestUrl(); + if (url != null && !url.isEmpty() && url.charAt(0) != '/' + && !url.startsWith("reg:")) { + url = "/" + url; + } + if (url.startsWith("reg:")) { // regular pattern + if (StringUtils.regMatch(url.substring(4), pattern)) { + result.add(action); + } + } else if (url.contains(":")) { + String urlParamRemoved = URLUtils.removeParamsInUrl(url); + String realUrlParamRemoved = URLUtils + .removeRealParamsInUrl(pattern); + if (urlParamRemoved.contains(realUrlParamRemoved) || + realUrlParamRemoved.contains(urlParamRemoved)) { + result.add(action); + } + } else { // normal pattern + if (url.contains(pattern)) { + result.add(action); + } + } } - return actionList; + + return result; + + // process /:id/ cases + // boolean urlParalized = false; + // String patternOrignial = pattern; + // if (pattern.contains(":")) { + // urlParalized = true; + // pattern = pattern.substring(0, pattern.indexOf(":")); + // } + + /** + * StringBuilder sb = new StringBuilder(); + * sb.append("SELECT a.id FROM tb_action a ") + * .append("JOIN tb_action_and_page ap ON ap.action_id = a.id ") + * .append("JOIN tb_page p ON p.id = ap.page_id ") + * .append("JOIN tb_module m ON m.id = p.module_id ") .append( + * "WHERE LOCATE(:pattern, a.request_url) != 0 AND m.project_id = :projectId " + * ); + * + * String sql = sb.toString(); Query query = + * getSession().createSQLQuery(sql); query.setString("pattern", + * pattern); query.setInteger("projectId", projectId); List + * list = query.list(); List actionList = new + * ArrayList(); for (int id : list) { + * actionList.add(getAction(id)); } + */ + + // URL parameters filter + /** + * if (urlParalized) { List filteredActionList = new + * ArrayList(); for (Action a : actionList) { String u = + * a.getRequestUrl(); if (u.contains("?")) { u = u.substring(0, + * u.indexOf("?")); } u = StringUtils.removeParamsInUrl(u); + * patternOrignial = StringUtils .removeParamsInUrl(patternOrignial); if + * (u != null && patternOrignial != null && u.equals(patternOrignial)) { + * filteredActionList.add(a); } } actionList = filteredActionList; } + */ + // return actionList; } @SuppressWarnings("unchecked") @@ -377,7 +503,7 @@ public List getProjectListByGroup(int id) { query.setInteger("id", id); return query.list(); } - + @SuppressWarnings("unchecked") @Override public List search(String key) { @@ -386,4 +512,37 @@ public List search(String key) { query.setString("key", "%" + key + "%"); return query.list(); } + + @SuppressWarnings({ "rawtypes" }) + private List getActionListOfProject(int projectId) { + List list = new ArrayList(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.id "); + sql.append("FROM tb_project p "); + sql.append("JOIN tb_module m ON m.project_id = p.id "); + sql.append("JOIN tb_page ON tb_page.module_id = m.id "); + sql.append("JOIN tb_action_and_page anp ON anp.page_id = tb_page.id "); + sql.append("JOIN tb_action a ON a.id = anp.action_id "); + sql.append("WHERE p.id = :projectId "); + Query query = getSession().createSQLQuery(sql.toString()); + query.setInteger("projectId", projectId); + + List result = query.list(); + List ids = new ArrayList(); + for (Object r : result) { + ids.add((Integer) r); + } + for (Integer id : ids) { + list.add(this.getAction(id)); + } + return list; + } + + @Override + public List selectMockNumTopNProjectList(int limit) { + String hqlByUser = "from Project order by mockNum desc"; + Query query = getSession().createQuery(hqlByUser); + return query.setMaxResults(limit).list(); + } + } diff --git a/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml index a0f9a42d3..792d88d56 100644 --- a/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml +++ b/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml @@ -4,7 +4,7 @@ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> - + @@ -17,6 +17,9 @@ + + + diff --git a/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml index cbf34bb7b..05eb4caf3 100644 --- a/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml +++ b/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml @@ -22,6 +22,11 @@ 分组ID + + + MOCK调用次数 + + 当前版本 diff --git a/src/com/taobao/rigel/rap/project/service/ProjectMgr.java b/src/com/taobao/rigel/rap/project/service/ProjectMgr.java index e2782a9be..d5d8e6d00 100644 --- a/src/com/taobao/rigel/rap/project/service/ProjectMgr.java +++ b/src/com/taobao/rigel/rap/project/service/ProjectMgr.java @@ -1,6 +1,7 @@ package com.taobao.rigel.rap.project.service; import java.util.List; +import java.util.Map; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.project.bo.Action; @@ -52,6 +53,8 @@ public interface ProjectMgr { */ Project getProject(int id); + Project getProject(int id, String ver); + /** * get module by id * @@ -77,7 +80,7 @@ public interface ProjectMgr { * @return */ String updateProject(int id, String projectData, - String deletedObjectListData); + String deletedObjectListData, Map actionIdMap); /** * get number of project list usually used for pager @@ -103,7 +106,7 @@ String updateProject(int id, String projectData, * @param page */ void loadParamIdListForPage(Page page); - + /** * get matched action list based on URL pattern * @@ -115,6 +118,7 @@ String updateProject(int id, String projectData, /** * get project list by group id + * * @param id * @return */ @@ -127,4 +131,46 @@ String updateProject(int id, String projectData, * @return */ List search(String key); + + /** + * get action + * + * @param id + * @return + */ + Action getAction(long id); + + Action getAction(long id, String ver, int projectId); + + /** + * update doc + * + * @param project id + */ + void updateDoc(int projectId); + + List getProjectList(); + + long getProjectNum(); + + long getModuleNum(); + + long getPageNum(); + + long getActionNum(); + + long getParametertNum(); + + long getCheckInNum(); + + long getMockNumInTotal(); + + List selectMockNumTopNProjectList(int limit); + + /** + * update Action.disableCache + * + * @param projectId + */ + void updateCache(int projectId); } diff --git a/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java b/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java index 98058bf57..97379b93e 100644 --- a/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java +++ b/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java @@ -1,13 +1,15 @@ package com.taobao.rigel.rap.project.service.impl; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; +import java.util.*; +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.account.service.AccountMgr; import com.taobao.rigel.rap.common.ArrayUtils; +import com.taobao.rigel.rap.common.HTTPUtils; +import com.taobao.rigel.rap.common.SystemConstant; import com.taobao.rigel.rap.organization.bo.Group; import com.taobao.rigel.rap.organization.dao.OrganizationDao; import com.taobao.rigel.rap.project.bo.Action; @@ -17,11 +19,27 @@ import com.taobao.rigel.rap.project.bo.Project; import com.taobao.rigel.rap.project.dao.ProjectDao; import com.taobao.rigel.rap.project.service.ProjectMgr; +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.dao.WorkspaceDao; public class ProjectMgrImpl implements ProjectMgr { private ProjectDao projectDao; private OrganizationDao organizationDao; + private AccountMgr accountMgr; + private WorkspaceDao workspaceDao; + + public void setWorkspaceDao(WorkspaceDao workspaceDao) { + this.workspaceDao = workspaceDao; + } + + public AccountMgr getAccountMgr() { + return accountMgr; + } + + public void setAccountMgr(AccountMgr accountMgr) { + this.accountMgr = accountMgr; + } public OrganizationDao getOrganizationDao() { return organizationDao; @@ -65,13 +83,26 @@ public List getProjectList(User user, int curPageNum, int pageSize) { public int addProject(Project project) { project.setUpdateTime(new Date()); project.setCreateDate(new Date()); + List usersInformed = new ArrayList(); for (String account : project.getMemberAccountList()) { User user = accountDao.getUser(account); if (user != null) { - project.addMember(user); + boolean addSuccess = project.addMember(user); + if (addSuccess) { + usersInformed.add(user); + } } } int result = projectDao.addProject(project); + for (User u : usersInformed) { + Notification o = new Notification(); + o.setTypeId((short)2); + o.setTargetUser(project.getUser()); + o.setUser(u); + o.setParam1(new Integer(result).toString()); + o.setParam2(project.getName()); + accountMgr.addNotification(o); + } Group g = organizationDao.getGroup(project.getGroupId()); if (g.getProductionLineId() > 0) { @@ -108,7 +139,16 @@ public int updateProject(Project outerProject) { for (String account : outerProject.getMemberAccountList()) { User user = accountDao.getUser(account); if (user != null) { - project.addMember(user); + boolean addSuccess = project.addMember(user); + if (addSuccess) { + Notification o = new Notification(); + o.setTypeId((short)2); + o.setTargetUser(outerProject.getUser()); + o.setUser(user); + o.setParam1(new Integer(outerProject.getId()).toString()); + o.setParam2(outerProject.getName()); + accountMgr.addNotification(o); + } } } @@ -136,7 +176,18 @@ public Project getProject(int id) { return projectDao.getProject(id); } - @Override + @Override + public Project getProject(int id, String ver) { + CheckIn check = workspaceDao.getVersion(id, ver); + String projectData = check.getProjectData(); + + Gson gson = new Gson(); + Project p = gson.fromJson(projectData, Project.class); + p.setVersion(check.getVersion()); + return p; + } + + @Override public Module getModule(int id) { return projectDao.getModule(id); } @@ -148,8 +199,8 @@ public Page getPage(int id) { @Override public String updateProject(int id, String projectData, - String deletedObjectListData) { - return projectDao.updateProject(id, projectData, deletedObjectListData); + String deletedObjectListData, Map actionIdMap) { + return projectDao.updateProject(id, projectData, deletedObjectListData, actionIdMap); } @Override @@ -226,4 +277,92 @@ public List getProjectListByGroup(int id) { public List search(String key) { return projectDao.search(key); } + + @Override + public Action getAction(long id) { + return projectDao.getAction(id); + } + + @Override + public Action getAction(long id, String ver, int projectId) { + CheckIn check = workspaceDao.getVersion(projectId, ver); + Gson gson = new Gson(); + Project p = gson.fromJson(check.getProjectData(), Project.class); + return p.findAction(id); + } + + @Override + public void updateDoc(int projectId) { + try { + HTTPUtils.sendGet("http://" + SystemConstant.NODE_SERVER + "/api/generateDoc?projectId=" + projectId); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public List getProjectList() { + return projectDao.getProjectList(); + } + + @Override + public long getProjectNum() { + return projectDao.getProjectListNum(); + } + + @Override + public long getModuleNum() { + return projectDao.getModuleNum(); + } + + @Override + public long getPageNum() { + return projectDao.getPageNum(); + } + + @Override + public long getActionNum() { + return projectDao.getActionNum(); + } + + @Override + public long getParametertNum() { + return projectDao.getParametertNum(); + } + + @Override + public long getCheckInNum() { + return projectDao.getCheckInNum(); + } + + @Override + public long getMockNumInTotal() {return projectDao.getMockNumInTotal();} + + @Override + public List selectMockNumTopNProjectList(int limit) { + return projectDao.selectMockNumTopNProjectList(limit); + } + + @Override + public void updateCache(int projectId) { + Project project = getProject(projectId); + for (Module module : project.getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + updateActionCache(action); + } + } + } + } + + private void updateActionCache(Action action) { + action.setDisableCache(0); + for (Parameter param : action.getResponseParameterList()) { + String rules = param.getMockJsRules(); + if (rules != null && rules.contains("${") && rules.contains("}")) { + action.setDisableCache(1); + break; + } + } + } } diff --git a/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java b/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java index 248bf04df..1be2ae457 100644 --- a/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java +++ b/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java @@ -26,6 +26,37 @@ public class ProjectAction extends ActionBase { private int id; private List searchResult; + + private String ids; + + public String getIds() { + if (ids == null || ids.isEmpty()) { + return ""; + } + + String[] idList = ids.split(","); + String returnVal = ""; + Integer num = 0; + int counter = 0; + for (String id : idList) { + try { + num = Integer.parseInt(id); + counter++; + if (counter > 1) { + returnVal += ","; + } + returnVal += num.toString(); + + } catch (Exception ex) { + + } + } + return returnVal; + } + + public void setIds(String ids) { + this.ids = ids; + } public List getSearchResult() { return searchResult; @@ -162,14 +193,6 @@ public ProjectMgr getProjectMgr() { return projectMgr; } - /** - * set project manager - * - * @param projectMgr - * project manager - * @throws exceptions - * No exceptions thrown - */ public void setProjectMgr(ProjectMgr projectMgr) { this.projectMgr = projectMgr; } @@ -204,27 +227,11 @@ public void setProjectData(String projectData) { this.projectData = projectData; } - /** - * remove project - * - * @param id - * {int} id of the project to be removed - */ - public String removeProject() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().canManageProject(getId())) { - setErrMsg("您没有管理该项目的权限"); - return ERROR; - } - projectMgr.removeProject(getId()); - return myProjectList(); - } public String delete() { if (!isUserLogined()) return LOGIN; - if (!getCurUser().canManageProject(getId())) { + if (!getAccountMgr().canUserManageProject(getCurUserId(), getId())) { setErrMsg("您没有管理该项目的权限"); return ERROR; } @@ -232,28 +239,6 @@ public String delete() { return SUCCESS; } - private String addProject() { - if (!isUserLogined()) - return LOGIN; - Project project = new Project(); - project.setCreateDate(new Date()); - project.setUser(getCurUser()); - project.setIntroduction(getIntroduction()); - project.setName(getName()); - List memberAccountList = new ArrayList(); - String[] list = getMemberAccountListStr().split(","); - // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), - for (String item : list) { - String account = item.contains("(") ? item.substring(0, - item.indexOf("(")).trim() : item.trim(); - if (!account.equals("")) - memberAccountList.add(account); - } - project.setMemberAccountList(memberAccountList); - projectMgr.addProject(project); - return this.myProjectList(); - } - public String create() { if (!isUserLogined()) return LOGIN; @@ -283,41 +268,15 @@ public String create() { result.put("accounts", project.getMemberAccountListStr()); result.put("groupId", project.getGroupId()); result.put("isManagable", "true"); + result.put("creator", project.getUser().getUserBaseInfo()); setJson(new RapError(gson.toJson(result)).toString()); return SUCCESS; } - private String updateProject() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().canManageProject(getId())) { - setErrMsg("您没有管理该项目的权限"); - return ERROR; - } - Project project = new Project(); - project.setId(getId()); - project.setIntroduction(getIntroduction()); - project.setName(getName()); - - List memberAccountList = new ArrayList(); - String[] list = getMemberAccountListStr().split(","); - // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), - for (String item : list) { - - String account = item.contains("(") ? item.substring(0, - item.indexOf("(")).trim() : item.trim(); - if (!account.equals("")) - memberAccountList.add(account); - } - project.setMemberAccountList(memberAccountList); - projectMgr.updateProject(project); - return myProjectList(); - } - public String update() { if (!isUserLogined()) return LOGIN; - if (!getCurUser().canManageProject(getId())) { + if (!getAccountMgr().canUserManageProject(getCurUserId(), getId())) { setErrMsg("您没有管理该项目的权限"); return ERROR; } @@ -325,7 +284,7 @@ public String update() { project.setId(getId()); project.setIntroduction(getDesc()); project.setName(getName()); - + project.setUser(getCurUser()); List memberAccountList = new ArrayList(); String[] list = getAccounts().split(","); // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), @@ -355,53 +314,22 @@ public String update() { setJson(new RapError(gson.toJson(result)).toString()); return SUCCESS; } - - public String addOrUpdateProject() { - if (id == 0) { - return addProject(); - } else { - return updateProject(); - } - } - - public String myProjectList() { - if (!isUserLogined()) - return LOGIN; - - // query paging - super.initPager(); - int curPageNum = super.getPager().getCurPagerNum(); - int pageSize = super.getPager().getPagerSize(); - long totalRecNum = projectMgr.getProjectListNum(getCurUser()); - getPager().setTotalRecNum(totalRecNum); - - setProjectList(projectMgr.getProjectList(getCurUser(), curPageNum, - pageSize)); - return SUCCESS; - } - - public String myProject() { + + public String updateReleatedIds() { if (!isUserLogined()) return LOGIN; - if (!getCurUser().haveAccessOfProject(getId())) { - setErrMsg("你没有访问该项目的权限。"); + if (!getAccountMgr().canUserManageProject(getCurUserId(), getId())) { + setErrMsg("您没有管理该项目的权限"); return ERROR; } - setProject(projectMgr.getProject(getId())); - setJson(getProject().toString(Project.toStringType.TO_PAGE)); + + Project project = projectMgr.getProject(getId()); + project.setRelatedIds(getIds()); + projectMgr.updateProject(project); + return SUCCESS; } - public String projectDetailAjax() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().haveAccessOfProject(getId())) { - setErrMsg("你没有访问该项目的权限。"); - return ERROR; - } - return this.myProject(); - } - private String result; public String getResult() { diff --git a/src/com/taobao/rigel/rap/project/web/action/struts.xml b/src/com/taobao/rigel/rap/project/web/action/struts.xml index d5a712563..70f3258ff 100644 --- a/src/com/taobao/rigel/rap/project/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/project/web/action/struts.xml @@ -7,11 +7,6 @@ - - /project/myProjectList.vm - - /bcom/json.cb.vm @@ -32,34 +27,11 @@ /bcom/json.cb.vm - - /project/myProjectList.vm - - - - /project/myProject.vm - - - - /bcom/project.cb.vm - - - - /project/myProjectList.vm - - - - - text/plain - attachment; filename="${generatedFileName}" - outputStream - + + /bcom/json.cb.vm + diff --git a/src/com/taobao/rigel/rap/tester/bo/SSOUser.java b/src/com/taobao/rigel/rap/tester/bo/SSOUser.java new file mode 100644 index 000000000..7075f48b3 --- /dev/null +++ b/src/com/taobao/rigel/rap/tester/bo/SSOUser.java @@ -0,0 +1,11 @@ +package com.taobao.rigel.rap.tester.bo; + +public class SSOUser { + public SSOUser() { + + } + public String empId; + public String nickNameCn; + public String firstName; + public String lastName; +} diff --git a/src/com/taobao/rigel/rap/tester/bo/SSOUserRes.java b/src/com/taobao/rigel/rap/tester/bo/SSOUserRes.java new file mode 100644 index 000000000..5cd093f46 --- /dev/null +++ b/src/com/taobao/rigel/rap/tester/bo/SSOUserRes.java @@ -0,0 +1,15 @@ +package com.taobao.rigel.rap.tester.bo; + +/** + * Created by Bosn on 14-9-23. + */ +public class SSOUserRes { + public SSOUserRes() { + + } + + public SSOUser content; + + +} + diff --git a/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java b/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java index a8458109f..724648bfa 100644 --- a/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java +++ b/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java @@ -1,19 +1,22 @@ package com.taobao.rigel.rap.tester.web.action; -import java.util.List; - +import com.google.gson.Gson; import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.account.service.AccountMgr; -import com.taobao.rigel.rap.common.StringUtils; +import com.taobao.rigel.rap.common.ActionBase; +import com.taobao.rigel.rap.common.HTTPUtils; +import com.taobao.rigel.rap.common.SystemVisitorLog; import com.taobao.rigel.rap.project.bo.Page; import com.taobao.rigel.rap.project.service.ProjectMgr; -import com.opensymphony.xwork2.ActionSupport; +import com.taobao.rigel.rap.tester.bo.SSOUserRes; + +import java.util.List; +import java.util.Map; + -public class TesterAction extends ActionSupport { +public class TesterAction extends ActionBase { private static final long serialVersionUID = 1L; private ProjectMgr projectMgr; - private AccountMgr accountMgr; private int id; private Page page; private int projectId; @@ -34,14 +37,6 @@ public void setProjectMgr(ProjectMgr projectMgr) { this.projectMgr = projectMgr; } - public AccountMgr getAccountMgr() { - return accountMgr; - } - - public void setAccountMgr(AccountMgr accountMgr) { - this.accountMgr = accountMgr; - } - public int getId() { return id; } @@ -56,19 +51,47 @@ public String pageTester() { projectId = page.getModule().getProject().getId(); return SUCCESS; } + + public String test() { + SystemVisitorLog.clear(projectMgr); + System.out.println("Clear complete!"); + setJson("clear complete"); + return SUCCESS; + } /** * used for system configuration when new version deployed * @return */ - public String ___init___() { - List userList = accountMgr.getUserList(); - for (User user : userList) { - String password = user.getPassword(); - password = StringUtils.getMD5(password); - password = StringUtils.getMD5(password); - accountMgr._updatePassword(user.getAccount(), password); - } + public String ___init___() throws Exception { + /** + List list = getAccountMgr().getUserList(); + int count = 1000; + for (User u : list) { + if (count-- <=0) { + break; + } + String account = u.getAccount(); + String res = HTTPUtils.sendGet(""); + Gson gson = new Gson(); + SSOUserRes json = gson.fromJson(res, SSOUserRes.class); + if (json.content == null) + System.out.println("not Ali employee"); + else { + System.out.println("empId:" + json.content.empId); + if (json.content.nickNameCn != null && !json.content.nickNameCn.isEmpty()) { + u.setName(json.content.nickNameCn); + } else { + u.setName(json.content.lastName); + } + u.setRealname(json.content.lastName); + u.setEmpId(json.content.empId); + getAccountMgr().updateUser(u); + + } + } + */ + return SUCCESS; } } diff --git a/src/com/taobao/rigel/rap/tester/web/action/struts.xml b/src/com/taobao/rigel/rap/tester/web/action/struts.xml index ac0987ad2..2f1e9d1c8 100644 --- a/src/com/taobao/rigel/rap/tester/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/tester/web/action/struts.xml @@ -14,6 +14,10 @@ class="com.taobao.rigel.rap.tester.web.action.TesterAction" method="___init___"> /bcom/isOk.cb.vm + + /bcom/json.cb.vm + diff --git a/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java b/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java index c5cd105ad..a466d7828 100644 --- a/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java +++ b/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java @@ -24,5 +24,7 @@ public interface WorkspaceDao { CheckIn getVersion(int versionId); + CheckIn getVersion(int projectId, String version); + void prepareForVersionSwitch(CheckIn check); } diff --git a/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java b/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java index 1e99e946b..4a227387a 100644 --- a/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java +++ b/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java @@ -22,21 +22,21 @@ public class WorkspaceDaoImpl extends HibernateDaoSupport implements WorkspaceDao { private AccountDao accountDao; - + public AccountDao getAccountDao() { return accountDao; } - + public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } private ProjectDao projectDao; - + public ProjectDao getProjectDao() { return projectDao; } - + public void setProjectDao(ProjectDao projectDao) { this.projectDao = projectDao; } @@ -64,7 +64,7 @@ private Workspace addWorkspace(int projectId, long userId) { Workspace workspace = new Workspace(); workspace.setUser((User)session.load(User.class, userId)); workspace.setProject(project); - workspace.setProjectData(project.toString(Project.toStringType.TO_PARAMETER)); + workspace.setProjectData(project.toString(Project.TO_STRING_TYPE.TO_PARAMETER)); workspace.setProjectDataOriginal(workspace.getProjectData()); workspace.setUpdateDate(new Date()); int id = (Integer)session.save(workspace); @@ -120,6 +120,15 @@ public CheckIn getVersion(int versionId) { return (CheckIn) getSession().load(CheckIn.class, versionId); } + @Override + public CheckIn getVersion(int projectId, String version) { + Session session = getSession(); + Query query = session.createQuery("from CheckIn obj where obj.project.id = :projectId and obj.version = :version"); + query.setInteger("projectId", projectId); + query.setString("version", version); + return (CheckIn) query.uniqueResult(); + } + @Override public void prepareForVersionSwitch(CheckIn check) { Session session = getSession(); diff --git a/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java b/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java index 2f1eea7c9..3acd6fdb8 100644 --- a/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java +++ b/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java @@ -196,7 +196,7 @@ public String checkIn(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getName(), actionB.getName(), "name")); actionB.setName(actionA.getName()); } else if (!aChanged && bChanged){ @@ -211,7 +211,7 @@ public String checkIn(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getDescription(), actionB.getDescription(), "description")); actionB.setDescription(actionA.getDescription()); } else if (!aChanged && bChanged){ @@ -226,7 +226,7 @@ public String checkIn(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getRequestType(), actionB.getRequestType(), "requestType")); actionB.setRequestType(actionA.getRequestType()); } else if (!aChanged && bChanged){ @@ -241,7 +241,7 @@ public String checkIn(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getRequestUrl(), actionB.getRequestUrl(), "requestUrl")); actionB.setRequestUrl(actionA.getRequestUrl()); } else if (!aChanged && bChanged){ @@ -256,7 +256,7 @@ public String checkIn(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getResponseTemplate(), actionB.getResponseTemplate(), "responseTemplate")); actionB.setResponseTemplate(actionA.getResponseTemplate()); } else if (!aChanged && bChanged){ @@ -422,7 +422,7 @@ public String checkOut(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getName(), actionB.getName(), "name")); actionB.setName(actionA.getName()); } else if (!aChanged && bChanged){ @@ -437,7 +437,7 @@ public String checkOut(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getDescription(), actionB.getDescription(), "description")); actionB.setDescription(actionA.getDescription()); } else if (!aChanged && bChanged){ @@ -452,7 +452,7 @@ public String checkOut(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getRequestType(), actionB.getRequestType(), "requestType")); actionB.setRequestType(actionA.getRequestType()); } else if (!aChanged && bChanged){ @@ -467,7 +467,7 @@ public String checkOut(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getRequestUrl(), actionB.getRequestUrl(), "requestUrl")); actionB.setRequestUrl(actionA.getRequestUrl()); } else if (!aChanged && bChanged){ @@ -482,7 +482,7 @@ public String checkOut(String [] jsonList, long userId, int projectId) { // [TODO] conflict! } else if (aChanged && !bChanged) { // update - log.append(logTemplate(actionB.getId(), "action", "update", + log.append(logTemplate(Integer.parseInt(new Long(actionB.getId()).toString()), "action", "update", actionA.getResponseTemplate(), actionB.getResponseTemplate(), "responseTemplate")); actionB.setResponseTemplate(actionA.getResponseTemplate()); } else if (!aChanged && bChanged){ @@ -622,7 +622,7 @@ private Page findPage(Project p, int pageId) { return null; } - private Action findAction(Project p, int actionId) { + private Action findAction(Project p, long actionId) { for (Module module : p.getModuleList()) { for (Page page : module.getPageList()) { for (Action action : page.getActionList()) { diff --git a/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java b/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java index ad1c80090..7351715b5 100644 --- a/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java +++ b/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java @@ -3,11 +3,12 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.StringWriter; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import com.google.gson.Gson; +import com.taobao.rigel.rap.common.SystemConstant; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; @@ -15,6 +16,7 @@ import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; +import com.taobao.rigel.rap.account.bo.Notification; import com.taobao.rigel.rap.account.bo.User; import com.taobao.rigel.rap.common.ActionBase; import com.taobao.rigel.rap.common.ContextManager; @@ -31,14 +33,24 @@ public class WorkspaceAction extends ActionBase { private static final long serialVersionUID = 1L; + private boolean accessable; + + public boolean isAccessable() { + return accessable; + } + + public void setAccessable(boolean accessable) { + this.accessable = accessable; + } + private boolean mock; - + private int actionId; - + public int getActionId() { return actionId; } - + public void setActionId(int actionId) { this.actionId = actionId; } @@ -234,6 +246,8 @@ public void setIsLocked(boolean isLocked) { this.isLocked = isLocked; } + private static final org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getFormatterLogger(WorkspaceAction.class.getName()); + public String myWorkspace() { if (!isUserLogined()) { plsLogin(); @@ -241,10 +255,17 @@ public String myWorkspace() { + projectId); return LOGIN; } + Project p = projectMgr.getProject(getProjectId()); + if (p == null || p.getId() <= 0) { + setErrMsg("该项目不存在或已被删除,会不会是亲这个链接保存的太久了呢?0 .0"); + logger.error("Unexpected project id=%d", getProjectId()); + return ERROR; + } Workspace workspace = new Workspace(); - workspace.setProject(projectMgr.getProject(getProjectId())); + workspace.setProject(p); setWorkspaceJsonString(workspace.toString()); setWorkspace(workspace); + setAccessable(getAccountMgr().canUserManageProject(getCurUserId(), getProjectId())); return SUCCESS; } @@ -351,10 +372,10 @@ public String switchVersion() { CheckIn check = workspaceMgr.getVersion(getVersionId()); workspaceMgr.prepareForVersionSwitch(check); projectMgr.updateProject(check.getProject().getId(), - check.getProjectData(), "[]"); + check.getProjectData(), "[]", new HashMap()); Project project = projectMgr.getProject(check.getProject().getId()); String projectData = project - .toString(Project.toStringType.TO_PARAMETER); + .toString(Project.TO_STRING_TYPE.TO_PARAMETER); setJson("{\"projectData\":" + projectData + ", \"isOk\":true}"); project.setProjectData(projectData); projectMgr.updateProject(project); @@ -366,13 +387,24 @@ public String checkIn() throws Exception { if (curUser == null) { setErrMsg(LOGIN_WARN_MSG); setIsOk(false); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + + if (!getAccountMgr().canUserManageProject(getCurUserId(), getId())) { + setErrMsg("access deny"); + setIsOk(false); + logger.error("User %s trying to checkedin project(id=$d) and denied.", getCurAccount(), getId()); return JSON_ERROR; } // update project + Map actionIdMap = new HashMap(); projectMgr.updateProject(getId(), getProjectData(), - getDeletedObjectListData()); - Project project = projectMgr.getProject(getId()); + getDeletedObjectListData(), actionIdMap); + + + project = projectMgr.getProject(getId()); // generate one check-in of VSS mode submit CheckIn checkIn = new CheckIn(); @@ -380,7 +412,7 @@ public String checkIn() throws Exception { checkIn.setDescription(getDescription()); checkIn.setProject(project); checkIn.setProjectData(project - .toString(Project.toStringType.TO_PARAMETER)); + .toString(Project.TO_STRING_TYPE.TO_PARAMETER)); checkIn.setTag(getTag()); checkIn.setUser(curUser); checkIn.setVersion(project.getVersion()); @@ -403,7 +435,11 @@ public String checkIn() throws Exception { stringBuilder.append(","); } } - stringBuilder.append("],\"isOk\":true}"); + Gson g = new Gson(); + stringBuilder + .append("],\"actionIdMap\":") + .append(g.toJson(actionIdMap)) + .append(",\"isOk\":true}"); setJson(stringBuilder.toString()); // update project data @@ -413,6 +449,54 @@ public String checkIn() throws Exception { // unlock the workspace unlock(); + // notification for doc change + for (User user : project.getUserList()) { + Notification notification = new Notification(); + notification.setParam1(new Integer(id).toString()); + notification.setParam2(project.getName()); + notification.setTypeId((short) 1); + notification.setTargetUser(getCurUser()); + notification.setUser(user); + if (notification.getUser().getId() != getCurUserId()) + getAccountMgr().addNotification(notification); + } + + Notification notification = new Notification(); + notification.setParam1(new Integer(id).toString()); + notification.setParam2(project.getName()); + notification.setTypeId((short) 1); + notification.setTargetUser(getCurUser()); + notification.setUser(project.getUser()); + if (notification.getUser().getId() != getCurUserId()) + getAccountMgr().addNotification(notification); + + // unfinished + /** + Callable taskSub = new Callable() { + + @Override + public String call() throws Exception { + try { + // async update doc + projectMgr.updateDoc(id); + // async update disableCache + projectMgr.updateCache(id); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return null; + } + }; + + FutureTask futureTask = new FutureTask(taskSub); + Thread asyncThread = new Thread(futureTask); + asyncThread.start(); + logger.info("Future task CHECK_IN running..."); + */ + + + return SUCCESS; } @@ -448,7 +532,8 @@ public String lock() { .get(ContextManager.KEY_PROJECT_LOCK_LIST); if (projectLockList.get(curUserId) == null) { projectLockList.put(curUserId, getId()); - //System.out.println("user[" + curUserId + "] locked project["+ getId() + "]"); + // System.out.println("user[" + curUserId + "] locked project["+ + // getId() + "]"); } isOk = true; } @@ -470,8 +555,7 @@ public String unlock() { long userId = super.getCurUserId(); int projectId = (Integer) projectLockList.get(userId); projectLockList.remove(userId); - System.out.println("user[" + userId + "] unlock project[" - + projectId + "]"); + logger.info("user[%d] unlock project[%d]", userId, projectId); } return SUCCESS; } @@ -529,4 +613,20 @@ private User getLocker(int projectId) { return null; } + public String __init__() { + // prevent repeated intialization of servcie + + if (SystemConstant.serviceInitialized) { + return SUCCESS; + } + + SystemConstant.serviceInitialized = true; + + List list = projectMgr.getProjectList(); + for (Project p : list) { + projectMgr.updateDoc(p.getId()); + } + return SUCCESS; + } + } diff --git a/src/com/taobao/rigel/rap/workspace/web/action/struts.xml b/src/com/taobao/rigel/rap/workspace/web/action/struts.xml index 7bad05c47..e0003763f 100644 --- a/src/com/taobao/rigel/rap/workspace/web/action/struts.xml +++ b/src/com/taobao/rigel/rap/workspace/web/action/struts.xml @@ -10,7 +10,6 @@ - /account/login.vm /workspace/myWorkspace.vm + + + diff --git a/test/com/taobao/rigel/rap/common/StringUtilsTest.java b/test/com/taobao/rigel/rap/common/StringUtilsTest.java new file mode 100644 index 000000000..388c1d60c --- /dev/null +++ b/test/com/taobao/rigel/rap/common/StringUtilsTest.java @@ -0,0 +1,15 @@ +package com.taobao.rigel.rap.common; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class StringUtilsTest { + + @Test + public void testEscapeInH() throws Exception { + String str = StringUtils.escapeInH("<>"); + assertEquals(str, "<>"); + // assertEquals(str + "12", "<>"); + } +} \ No newline at end of file