Commit d0e1f676 authored by Administrator's avatar Administrator

小程序管理后台多路线改造

parent 48e3670c
...@@ -16,14 +16,10 @@ import java.util.List; ...@@ -16,14 +16,10 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
...@@ -61,7 +57,6 @@ public class ImportExcel { ...@@ -61,7 +57,6 @@ public class ImportExcel {
/** /**
* 构造函数 * 构造函数
* *
* @param path 导入文件,读取第一个工作表
* @param headerNum 标题行号,数据行号=标题行号+1 * @param headerNum 标题行号,数据行号=标题行号+1
* @throws InvalidFormatException * @throws InvalidFormatException
* @throws IOException * @throws IOException
...@@ -74,7 +69,6 @@ public class ImportExcel { ...@@ -74,7 +69,6 @@ public class ImportExcel {
/** /**
* 构造函数 * 构造函数
* *
* @param path 导入文件对象,读取第一个工作表
* @param headerNum 标题行号,数据行号=标题行号+1 * @param headerNum 标题行号,数据行号=标题行号+1
* @throws InvalidFormatException * @throws InvalidFormatException
* @throws IOException * @throws IOException
...@@ -87,7 +81,6 @@ public class ImportExcel { ...@@ -87,7 +81,6 @@ public class ImportExcel {
/** /**
* 构造函数 * 构造函数
* *
* @param path 导入文件
* @param headerNum 标题行号,数据行号=标题行号+1 * @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号 * @param sheetIndex 工作表编号
* @throws InvalidFormatException * @throws InvalidFormatException
...@@ -101,7 +94,6 @@ public class ImportExcel { ...@@ -101,7 +94,6 @@ public class ImportExcel {
/** /**
* 构造函数 * 构造函数
* *
* @param path 导入文件对象
* @param headerNum 标题行号,数据行号=标题行号+1 * @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号 * @param sheetIndex 工作表编号
* @throws InvalidFormatException * @throws InvalidFormatException
...@@ -115,7 +107,7 @@ public class ImportExcel { ...@@ -115,7 +107,7 @@ public class ImportExcel {
/** /**
* 构造函数 * 构造函数
* *
* @param file 导入文件对象 * @param multipartFile 导入文件对象
* @param headerNum 标题行号,数据行号=标题行号+1 * @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号 * @param sheetIndex 工作表编号
* @throws InvalidFormatException * @throws InvalidFormatException
...@@ -129,7 +121,7 @@ public class ImportExcel { ...@@ -129,7 +121,7 @@ public class ImportExcel {
/** /**
* 构造函数 * 构造函数
* *
* @param path 导入文件对象 * @param fileName 导入文件对象
* @param headerNum 标题行号,数据行号=标题行号+1 * @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号 * @param sheetIndex 工作表编号
* @throws InvalidFormatException * @throws InvalidFormatException
...@@ -198,8 +190,8 @@ public class ImportExcel { ...@@ -198,8 +190,8 @@ public class ImportExcel {
* @param column 获取单元格列号 * @param column 获取单元格列号
* @return 单元格值 * @return 单元格值
*/ */
public Object getCellValue(Row row, int column) { public static String getCellValue(Row row, int column) {
Object val = ""; String val = "";
try { try {
Cell cell = row.getCell(column); Cell cell = row.getCell(column);
...@@ -212,9 +204,9 @@ public class ImportExcel { ...@@ -212,9 +204,9 @@ public class ImportExcel {
} else if (cell.getCellTypeEnum() == CellType.FORMULA) { } else if (cell.getCellTypeEnum() == CellType.FORMULA) {
val = cell.getCellFormula(); val = cell.getCellFormula();
} else if (cell.getCellTypeEnum() == CellType.BOOLEAN) { } else if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
val = cell.getBooleanCellValue(); val = String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellTypeEnum() == CellType.ERROR) { } else if (cell.getCellTypeEnum() == CellType.ERROR) {
val = cell.getErrorCellValue(); val = String.valueOf(cell.getErrorCellValue());
} }
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -223,6 +215,15 @@ public class ImportExcel { ...@@ -223,6 +215,15 @@ public class ImportExcel {
return val; return val;
} }
public static void setCellStyle(XSSFWorkbook wb, XSSFCell cell){
XSSFCellStyle cellStyle = wb.createCellStyle();
XSSFFont font = wb.createFont();
font.setColor(Font.COLOR_RED);
font.setBold(true);
cellStyle.setFont(font);
cell.setCellStyle(cellStyle);
}
/** /**
* 获取导入数据列表 * 获取导入数据列表
* *
...@@ -281,6 +282,7 @@ public class ImportExcel { ...@@ -281,6 +282,7 @@ public class ImportExcel {
} }
// Field sorting // Field sorting
Collections.sort(annotationList, new Comparator<Object[]>() { Collections.sort(annotationList, new Comparator<Object[]>() {
@Override
public int compare(Object[] o1, Object[] o2) { public int compare(Object[] o1, Object[] o2) {
return new Integer(((ExcelField) o1[0]).sort()).compareTo( return new Integer(((ExcelField) o1[0]).sort()).compareTo(
new Integer(((ExcelField) o2[0]).sort())); new Integer(((ExcelField) o2[0]).sort()));
...@@ -297,7 +299,7 @@ public class ImportExcel { ...@@ -297,7 +299,7 @@ public class ImportExcel {
Row row = this.getRow(i); Row row = this.getRow(i);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (Object[] os : annotationList) { for (Object[] os : annotationList) {
Object val = this.getCellValue(row, column++); Object val = getCellValue(row, column++);
if (val != null) { if (val != null) {
ExcelField ef = (ExcelField) os[0]; ExcelField ef = (ExcelField) os[0];
// If is dict type, get dict value // If is dict type, get dict value
......
...@@ -35,5 +35,7 @@ public class CmptScoreRuleScoreInfo { ...@@ -35,5 +35,7 @@ public class CmptScoreRuleScoreInfo {
@JsonIgnore @JsonIgnore
private String insertTime; private String insertTime;
private String updateTime; private String updateTime;
private int roadId;
private int pathId;
} }
package com.dlbridge.jadp.plugins.cmpt.bean;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.util.Objects;
@Getter
@Setter
@Accessors(chain = true)
@ToString
@ApiModel(value = "项目", description = "项目")
public class Path {
@ApiModelProperty(value = "组别ID", notes = "组别ID")
private Integer roadId;
@ApiModelProperty(value = "赛事ID", notes = "赛事ID")
private Integer cmptId;
@ApiModelProperty(value = "路线ID", notes = "路线ID")
private Integer pathId;
@ApiModelProperty(value = "是否支持多路线", notes = "是否支持多路线")
private String isMultiRoute;
@ApiModelProperty(value = "路线名称", notes = "路线名称")
private String pathName;
@ApiModelProperty(value = "文件名称", notes = "文件名称")
private String fileName;
@ApiModelProperty(value = "文件地址", notes = "文件地址")
private String fileUrl;
@ApiModelProperty(value = "文件大小", notes = "单位kb")
private double fileSize;
private String createTime;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Path path = (Path) o;
return pathId.equals(path.pathId);
}
@Override
public int hashCode() {
return Objects.hash(pathId);
}
}
...@@ -15,6 +15,7 @@ public interface CmptScoreRuleScoreInfoMapper { ...@@ -15,6 +15,7 @@ public interface CmptScoreRuleScoreInfoMapper {
* @param cmptScoreRuleScoreInfo * @param cmptScoreRuleScoreInfo
*/ */
void saveScoreRuleScoreInfo(@Param("cmptScoreRuleScoreInfo") CmptScoreRuleScoreInfo cmptScoreRuleScoreInfo); void saveScoreRuleScoreInfo(@Param("cmptScoreRuleScoreInfo") CmptScoreRuleScoreInfo cmptScoreRuleScoreInfo);
void insertScoreBatch(@Param("list") List<CmptScoreRuleScoreInfo> list);
/** /**
* 根据号码牌获取用户的成绩 * 根据号码牌获取用户的成绩
...@@ -42,7 +43,7 @@ public interface CmptScoreRuleScoreInfoMapper { ...@@ -42,7 +43,7 @@ public interface CmptScoreRuleScoreInfoMapper {
* @param checkStatus * @param checkStatus
* @return * @return
*/ */
Integer getCmptScoreRuleScoreInfoToalNumer(@Param("cmptId") int cmptId, @Param("roadId") int roadId, @Param("ruleId") int ruleId,@Param("checkStatus") int checkStatus); Integer getCmptScoreRuleScoreInfoToalNumer(@Param("cmptId") int cmptId, @Param("roadId") int roadId, @Param("pathId") int pathId, @Param("ruleId") int ruleId,@Param("checkStatus") int checkStatus);
/** /**
* 分页获取用户提交的成绩 * 分页获取用户提交的成绩
...@@ -53,7 +54,7 @@ public interface CmptScoreRuleScoreInfoMapper { ...@@ -53,7 +54,7 @@ public interface CmptScoreRuleScoreInfoMapper {
* @param checkStatus * @param checkStatus
* @return * @return
*/ */
List<CmptScoreRuleScoreInfo> getCmptScoreRuleScoreInfoList(Pageable page, int cmptId, int roadId, int ruleId, int checkStatus); List<CmptScoreRuleScoreInfo> getCmptScoreRuleScoreInfoList(Pageable page, int cmptId, int roadId, int pathId, int ruleId, int checkStatus);
/** /**
* 批量审核,审核成绩结果为未通过 * 批量审核,审核成绩结果为未通过
...@@ -90,7 +91,7 @@ public interface CmptScoreRuleScoreInfoMapper { ...@@ -90,7 +91,7 @@ public interface CmptScoreRuleScoreInfoMapper {
* @param ruleId * @param ruleId
* @return * @return
*/ */
HashMap<String,Object> getCmptScoreRuleScoreInfoStatistics(@Param("cmptId") int cmptId,@Param("roadId") int roadId,@Param("ruleId") int ruleId); HashMap<String, Object> getCmptScoreRuleScoreInfoStatistics(@Param("cmptId") int cmptId, @Param("roadId") int roadId, @Param("ruleId") int ruleId, @Param("pathId") int pathId);
/** /**
* 根据markNo,ruleId获取CmptScoreRuleScoreInfo * 根据markNo,ruleId获取CmptScoreRuleScoreInfo
......
...@@ -6,6 +6,17 @@ ...@@ -6,6 +6,17 @@
INSERT INTO gk_cmpt_score_rule_scoreinfo(cmptId,rule_id,mark_no,subsectionTime,subsectionscore,subsectionMileage,cmptPace,checkStatus,isDelete,insertTime,updateTime) INSERT INTO gk_cmpt_score_rule_scoreinfo(cmptId,rule_id,mark_no,subsectionTime,subsectionscore,subsectionMileage,cmptPace,checkStatus,isDelete,insertTime,updateTime)
VALUES(#{cmptScoreRuleScoreInfo.cmptId},#{cmptScoreRuleScoreInfo.ruleId},#{cmptScoreRuleScoreInfo.markNo},#{cmptScoreRuleScoreInfo.subsectionTime},#{cmptScoreRuleScoreInfo.subsectionscore},#{cmptScoreRuleScoreInfo.subsectionMileage},#{cmptScoreRuleScoreInfo.cmptPace},#{cmptScoreRuleScoreInfo.checkStatus},0,now(),now()) VALUES(#{cmptScoreRuleScoreInfo.cmptId},#{cmptScoreRuleScoreInfo.ruleId},#{cmptScoreRuleScoreInfo.markNo},#{cmptScoreRuleScoreInfo.subsectionTime},#{cmptScoreRuleScoreInfo.subsectionscore},#{cmptScoreRuleScoreInfo.subsectionMileage},#{cmptScoreRuleScoreInfo.cmptPace},#{cmptScoreRuleScoreInfo.checkStatus},0,now(),now())
</insert> </insert>
<insert id="insertScoreBatch" parameterType="java.util.List">
insert into gk_cmpt_score_rule_scoreinfo (
cmptId,rule_id,mark_no,subsectionTime,subsectionscore,subsectionMileage,cmptPace,checkStatus,isDelete,insertTime,updateTime,score_way,is_end,road_id,path_id
)
values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.cmptId},#{item.ruleId},#{item.markNo},#{item.subsectionTime},#{item.subsectionscore},#{item.subsectionMileage},#{item.cmptPace},#{item.checkStatus},0,now(),now(),1,1,#{item.roadId},#{item.pathId}
)
</foreach>
</insert>
<select id="getScoreRuleScoreInfoByMarkNo" resultType="com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo"> <select id="getScoreRuleScoreInfoByMarkNo" resultType="com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo">
select id,cmptId,rule_id as ruleId,mark_no as markNo,subsectionTime,subsectionscore,subsectionMileage,cmptPace from gk_cmpt_score_rule_scoreinfo where cmptId=#{cmptId} and mark_no=#{markNo} and checkStatus=1 and isDelete=0 select id,cmptId,rule_id as ruleId,mark_no as markNo,subsectionTime,subsectionscore,subsectionMileage,cmptPace from gk_cmpt_score_rule_scoreinfo where cmptId=#{cmptId} and mark_no=#{markNo} and checkStatus=1 and isDelete=0
</select> </select>
...@@ -14,7 +25,18 @@ ...@@ -14,7 +25,18 @@
and mark_no=#{markNo} and isDelete=0 limit 1 and mark_no=#{markNo} and isDelete=0 limit 1
</select> </select>
<select id="getCmptScoreRuleScoreInfoToalNumer" resultType="int"> <select id="getCmptScoreRuleScoreInfoToalNumer" resultType="int">
select count(1) from geerunner.cmpt_enroll as a left join gk_cmpt_score_rule_scoreinfo as b on a.cmpt_id=b.cmptId and a.nick_id=b.mark_no where a.cmpt_id=#{cmptId} and a.cmpt_item=#{roadId} and rule_id=#{ruleId} and checkStatus=#{checkStatus} and a.del_flg=0 and b.isDelete=0 select count(1)
from geerunner.cmpt_enroll as a
left join gk_cmpt_score_rule_scoreinfo as b on a.cmpt_id = b.cmptId and a.nick_id = b.mark_no
where a.cmpt_id = #{cmptId}
and a.cmpt_item = #{roadId}
and rule_id = #{ruleId}
and checkStatus = #{checkStatus}
<if test="pathId > 0">
and b.path_id = #{pathId}
</if>
and a.del_flg = 0
and b.isDelete = 0
</select> </select>
<select id="getCmptScoreRuleScoreInfoList" resultType="com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo"> <select id="getCmptScoreRuleScoreInfoList" resultType="com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo">
select b.id as cmptScoreRuleScoreId,a.member_name select b.id as cmptScoreRuleScoreId,a.member_name
...@@ -25,6 +47,9 @@ ...@@ -25,6 +47,9 @@
as b on a.cmpt_id=b.cmptId and a.nick_id=b.mark_no as b on a.cmpt_id=b.cmptId and a.nick_id=b.mark_no
where a.cmpt_id=#{cmptId} and a.cmpt_item=#{roadId} and rule_id=#{ruleId} where a.cmpt_id=#{cmptId} and a.cmpt_item=#{roadId} and rule_id=#{ruleId}
and checkStatus=#{checkStatus} and a.del_flg=0 and b.isDelete=0 and checkStatus=#{checkStatus} and a.del_flg=0 and b.isDelete=0
<if test="pathId > 0">
and b.path_id = #{pathId}
</if>
order by updateTime desc limit #{page.offset},#{page.size} order by updateTime desc limit #{page.offset},#{page.size}
</select> </select>
...@@ -61,7 +86,12 @@ ...@@ -61,7 +86,12 @@
count(case when checkStatus=2 then 1 end) as 'nopass' count(case when checkStatus=2 then 1 end) as 'nopass'
from geerunner.cmpt_enroll as a from geerunner.cmpt_enroll as a
left join gk_cmpt_score_rule_scoreinfo as b on a.cmpt_id=b.cmptId and a.nick_id=b.mark_no left join gk_cmpt_score_rule_scoreinfo as b on a.cmpt_id=b.cmptId and a.nick_id=b.mark_no
where a.cmpt_id=#{cmptId} and a.cmpt_item=#{roadId} and rule_id=#{ruleId} and a.del_flg=0 and b.isDelete=0 where 1=1
and a.del_flg=0 and b.isDelete=0
and a.cmpt_id=#{cmptId} and a.cmpt_item=#{roadId} and rule_id=#{ruleId}
<if test="pathId > 0">
and a.path_id = #{pathId}
</if>
</select> </select>
<select id="getCmptScoreRuleScoreInfoByruleIdAndMarkNo" resultType="com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo"> <select id="getCmptScoreRuleScoreInfoByruleIdAndMarkNo" resultType="com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo">
......
package com.dlbridge.jadp.plugins.cmpt.dao.mapper; package com.dlbridge.jadp.plugins.cmpt.dao.mapper;
import com.dlbridge.jadp.plugins.cmpt.bean.Equipment; import com.dlbridge.jadp.plugins.cmpt.bean.Equipment;
import com.dlbridge.jadp.plugins.cmpt.bean.Path;
import com.dlbridge.jadp.plugins.cmpt.bean.Road; import com.dlbridge.jadp.plugins.cmpt.bean.Road;
import com.dlbridge.jadp.plugins.cmpt.bean.RoadGpsPoint; import com.dlbridge.jadp.plugins.cmpt.bean.RoadGpsPoint;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
...@@ -17,6 +18,8 @@ public interface RoadMapper { ...@@ -17,6 +18,8 @@ public interface RoadMapper {
int delete(Integer roadId); int delete(Integer roadId);
List<Road> queryRoads(Integer cmptId); List<Road> queryRoads(Integer cmptId);
List<Road> queryRoadsMultiPath(Integer cmptId);
List<Path> queryPaths(Integer cmptId, Integer roadId);
int saveGps(RoadGpsPoint point); int saveGps(RoadGpsPoint point);
......
...@@ -2,7 +2,38 @@ ...@@ -2,7 +2,38 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dlbridge.jadp.plugins.cmpt.dao.mapper.RoadMapper"> <mapper namespace="com.dlbridge.jadp.plugins.cmpt.dao.mapper.RoadMapper">
<select id="queryPaths" resultType="com.dlbridge.jadp.plugins.cmpt.bean.Path">
select a.road_id roadId
, a.cmpt_id cmptId
, a.file_name fileName
, a.file_url fileUrl
, a.file_size fileSize
, a.id pathId
, a.path_name pathName
, a.create_time createTime
from gk_roads_gps a
WHERE 1=1
AND a.cmpt_id = #{cmptId}
AND a.road_id = #{roadId}
</select>
<select id="queryRoads" resultType="com.dlbridge.jadp.plugins.cmpt.bean.Road"> <select id="queryRoads" resultType="com.dlbridge.jadp.plugins.cmpt.bean.Road">
select a.road_id roadId
, a.cmpt_id cmptId
, a.road_name name
, a.file_name fileName
, a.file_url fileUrl
, a.times
, a.file_size fileSize
, b.item_type roadType
, case when b.item_type = 2 then '团队赛' when b.item_type = 1 then '个人赛' else '其他' end roadTypeName
from gk_road a
LEFT JOIN geerunner.cmpt_item b ON a.cmpt_id = b.cmpt_id AND a.road_id = b.item_id
WHERE a.cmpt_id = #{cmptId}
AND a.is_delete = 0
</select>
<select id="queryRoadsMultiPath" resultType="com.dlbridge.jadp.plugins.cmpt.bean.Road">
select a.road_id roadId select a.road_id roadId
, a.cmpt_id cmptId , a.cmpt_id cmptId
, a.road_name name , a.road_name name
......
...@@ -6,6 +6,8 @@ import com.dlbridge.jadp.plugins.cmpt.dao.mapper.CmptScoreRuleScoreInfoMapper; ...@@ -6,6 +6,8 @@ import com.dlbridge.jadp.plugins.cmpt.dao.mapper.CmptScoreRuleScoreInfoMapper;
import com.dlbridge.jadp.plugins.cmpt.utils.Page; import com.dlbridge.jadp.plugins.cmpt.utils.Page;
import com.dlbridge.jadp.plugins.cmpt.utils.PageFactory; import com.dlbridge.jadp.plugins.cmpt.utils.PageFactory;
import com.dlbridge.jadp.plugins.cmpt.utils.date.DateUtil; import com.dlbridge.jadp.plugins.cmpt.utils.date.DateUtil;
import com.neusoft.www.utils.web.Result;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -115,9 +117,9 @@ public class CmptScoreRuleScoreInfoService { ...@@ -115,9 +117,9 @@ public class CmptScoreRuleScoreInfoService {
* @return * @return
* size=10&page=0&cmptId=11888&checkstatus=0&roadId=21296&ruleId=79 * size=10&page=0&cmptId=11888&checkstatus=0&roadId=21296&ruleId=79
*/ */
public Page<List<CmptScoreRuleScoreInfo>> getCmptScoreRuleScoreInfo(Pageable page, int cmptId, int roadId, int ruleId,int checkstatus){ public Page<List<CmptScoreRuleScoreInfo>> getCmptScoreRuleScoreInfo(Pageable page, int cmptId, int roadId, int pathId, int ruleId,int checkstatus){
long count = cmptScoreRuleScoreInfoMapper.getCmptScoreRuleScoreInfoToalNumer(cmptId,roadId,ruleId,checkstatus); long count = cmptScoreRuleScoreInfoMapper.getCmptScoreRuleScoreInfoToalNumer(cmptId,roadId,pathId,ruleId,checkstatus);
List<CmptScoreRuleScoreInfo> list = cmptScoreRuleScoreInfoMapper.getCmptScoreRuleScoreInfoList(page,cmptId,roadId,ruleId,checkstatus); List<CmptScoreRuleScoreInfo> list = cmptScoreRuleScoreInfoMapper.getCmptScoreRuleScoreInfoList(page,cmptId,roadId, pathId,ruleId,checkstatus);
List<CmptScoreFieldValue> cmptScoreFieldValueList=cmptScoreFieldValueService.getCmptScoreFieldValueByCmptIdAndRuleId(cmptId,ruleId); List<CmptScoreFieldValue> cmptScoreFieldValueList=cmptScoreFieldValueService.getCmptScoreFieldValueByCmptIdAndRuleId(cmptId,ruleId);
for(CmptScoreRuleScoreInfo cmptScoreRuleScoreInfo:list){ for(CmptScoreRuleScoreInfo cmptScoreRuleScoreInfo:list){
List<String> filterResutList=cmptScoreFieldValueList.parallelStream().filter(s->s.getMarkNo()!=null&&s.getMarkNo().equals(cmptScoreRuleScoreInfo.getMarkNo())).map(CmptScoreFieldValue::getScoreFieldValue).collect(Collectors.toList()); List<String> filterResutList=cmptScoreFieldValueList.parallelStream().filter(s->s.getMarkNo()!=null&&s.getMarkNo().equals(cmptScoreRuleScoreInfo.getMarkNo())).map(CmptScoreFieldValue::getScoreFieldValue).collect(Collectors.toList());
...@@ -159,8 +161,8 @@ public class CmptScoreRuleScoreInfoService { ...@@ -159,8 +161,8 @@ public class CmptScoreRuleScoreInfoService {
* @param ruleId * @param ruleId
* @return * @return
*/ */
public HashMap<String,Object> getCmptScoreRuleScoreInfoStatistics(int cmptId,int roadId,int ruleId){ public HashMap<String,Object> getCmptScoreRuleScoreInfoStatistics(int cmptId,int roadId,int ruleId,int pathId){
HashMap<String,Object> cmptScoreRuleScoreInfoStatistics=cmptScoreRuleScoreInfoMapper.getCmptScoreRuleScoreInfoStatistics(cmptId,roadId,ruleId); HashMap<String,Object> cmptScoreRuleScoreInfoStatistics=cmptScoreRuleScoreInfoMapper.getCmptScoreRuleScoreInfoStatistics(cmptId,roadId,ruleId,pathId);
return cmptScoreRuleScoreInfoStatistics; return cmptScoreRuleScoreInfoStatistics;
} }
...@@ -209,4 +211,5 @@ public class CmptScoreRuleScoreInfoService { ...@@ -209,4 +211,5 @@ public class CmptScoreRuleScoreInfoService {
public List<CmptScoreRuleScoreInfo> getScoreInfosBycmptIdAndMarkNoEnd(int cmptId, String markNo) { public List<CmptScoreRuleScoreInfo> getScoreInfosBycmptIdAndMarkNoEnd(int cmptId, String markNo) {
return cmptScoreRuleScoreInfoMapper.getScoreInfosBycmptIdAndMarkNoEnd(cmptId,markNo); return cmptScoreRuleScoreInfoMapper.getScoreInfosBycmptIdAndMarkNoEnd(cmptId,markNo);
} }
} }
package com.dlbridge.jadp.plugins.cmpt.service; package com.dlbridge.jadp.plugins.cmpt.service;
import com.dlbridge.jadp.common.utils.excel.ImportExcel;
import com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRule; import com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRule;
import com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRuleScoreInfo;
import com.dlbridge.jadp.plugins.cmpt.bean.ScoreRuleMap; import com.dlbridge.jadp.plugins.cmpt.bean.ScoreRuleMap;
import com.dlbridge.jadp.plugins.cmpt.bean.UserScoreExcelBean; import com.dlbridge.jadp.plugins.cmpt.bean.UserScoreExcelBean;
import com.dlbridge.jadp.plugins.cmpt.dao.mapper.CmptScoreRuleMapper; import com.dlbridge.jadp.plugins.cmpt.dao.mapper.CmptScoreRuleMapper;
import com.dlbridge.jadp.plugins.cmpt.dao.mapper.CmptScoreRuleScoreInfoMapper;
import com.neusoft.www.utils.web.Result;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
@Log4j2
@Service @Service
@Transactional @Transactional
public class CmptScoreRuleService { public class CmptScoreRuleService {
@Resource @Resource
CmptScoreRuleMapper cmptScoreRuleMapper; CmptScoreRuleMapper cmptScoreRuleMapper;
@Resource
CmptScoreRuleScoreInfoMapper cmptScoreRuleScoreInfoMapper;
/** /**
* 根据赛事成绩规则Id,判断是更新成绩规则还是插入成绩规则 * 根据赛事成绩规则Id,判断是更新成绩规则还是插入成绩规则
* @param cmptScoreRules * @param cmptScoreRules
...@@ -106,4 +125,125 @@ public class CmptScoreRuleService { ...@@ -106,4 +125,125 @@ public class CmptScoreRuleService {
public void updateDisplayCount(Integer cmptId, Integer displayCount) { public void updateDisplayCount(Integer cmptId, Integer displayCount) {
cmptScoreRuleMapper.updateDisplayCount(cmptId,displayCount); cmptScoreRuleMapper.updateDisplayCount(cmptId,displayCount);
} }
public Result importScoreExcel(XSSFWorkbook wb, int cmptId, int roadId, int pathId){
try {
XSSFSheet sheet = wb.getSheetAt(0);
List<CmptScoreRuleScoreInfo> scoreList = new ArrayList<>();
// 循环Excel数据
for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
CmptScoreRuleScoreInfo ruleScoreInfo = new CmptScoreRuleScoreInfo();
XSSFRow row = sheet.getRow(rowNum);
int lastcolNum = row.getLastCellNum();
if(null == row){
continue;
}
// 号码牌列取值
String markNo = ImportExcel.getCellValue(row,0);
if (StringUtils.isBlank(markNo)){
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("号码牌不能为空!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
ruleScoreInfo.setMarkNo(markNo);
// 成绩列取值
String subsectionscore = ImportExcel.getCellValue(row,1);
if (StringUtils.isBlank(subsectionscore)){
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("成绩不能为空!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
int score = 0;
try {
score = Integer.parseInt(subsectionscore);
ruleScoreInfo.setSubsectionscore(score);
} catch (NumberFormatException e) {
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("成绩单元格不是数字!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
// 里程列取值
String subsectionMileage = ImportExcel.getCellValue(row,2);
if (StringUtils.isBlank(subsectionMileage)){
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("里程不能为空!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
int mileage = 0;
try {
mileage = Integer.parseInt(subsectionMileage);
ruleScoreInfo.setSubsectionMileage(mileage);
} catch (NumberFormatException e) {
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("里程单元格不是数字!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
// 成绩提交时间列取值
String subsectionTime = ImportExcel.getCellValue(row,3);
if (StringUtils.isBlank(subsectionTime)){
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("成绩提交时间不能为空!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.parse(subsectionTime);
ruleScoreInfo.setSubsectionTime(subsectionTime);
} catch (ParseException e) {
XSSFCell cell = row.createCell(lastcolNum);
cell.setCellValue("成绩提交时间格式不正确!");
ImportExcel.setCellStyle(wb, cell);
return Result.fail();
}
// 配速计算
float cmptPace = paceCalculator(score,mileage);
ruleScoreInfo.setCmptPace(cmptPace);
// 其他参数设置
ruleScoreInfo.setCmptId(cmptId);
ruleScoreInfo.setRoadId(roadId);
ruleScoreInfo.setPathId(pathId);
scoreList.add(ruleScoreInfo);
}
if(!scoreList.isEmpty()){
cmptScoreRuleScoreInfoMapper.insertScoreBatch(scoreList);
}
} catch (NumberFormatException e) {
log.info("===== 导入成绩Excel异常:{}",e.getMessage());
return Result.fail();
}
return Result.success();
}
/**
* 根据duration和mileage计算配速
* mileage为里程,单位是米
* duration为耗时,单位为秒
* @param duration
* @param mileage
* @return
*/
public static float paceCalculator(int duration,int mileage){
if(mileage == 0){
return 0;
}
DecimalFormat decimalFormat=new DecimalFormat(".000000");
float cmptPace = Float.parseFloat(decimalFormat.format(duration / (mileage/1000.0)));;
return cmptPace;
}
} }
package com.dlbridge.jadp.plugins.cmpt.service; package com.dlbridge.jadp.plugins.cmpt.service;
import com.dlbridge.jadp.plugins.cmpt.bean.Path;
import com.dlbridge.jadp.plugins.cmpt.bean.Road; import com.dlbridge.jadp.plugins.cmpt.bean.Road;
import com.dlbridge.jadp.plugins.cmpt.bean.RoadGpsPoint; import com.dlbridge.jadp.plugins.cmpt.bean.RoadGpsPoint;
import com.dlbridge.jadp.plugins.cmpt.dao.mapper.RoadMapper; import com.dlbridge.jadp.plugins.cmpt.dao.mapper.RoadMapper;
...@@ -42,8 +43,17 @@ public class RoadService { ...@@ -42,8 +43,17 @@ public class RoadService {
return roadMapper.delete(id); return roadMapper.delete(id);
} }
/**
* 根据赛事、组别 获取路线列表
* @param cmptId 赛事ID
* @param roadId 路线ID
* @return 路线列表
*/
public List<Path> queryPaths(Integer cmptId, Integer roadId){
return roadMapper.queryPaths(cmptId, roadId);
}
public List<Road> queryRoads(Integer cmptId) { public List<Road> queryRoads(Integer cmptId) {
log.info("RoadService enter"); log.info("=====queryRoads -> RoadService enter");
List<Road> roads = remoteService.getRoads(cmptId); List<Road> roads = remoteService.getRoads(cmptId);
if(roads == null) { if(roads == null) {
return null; return null;
...@@ -80,6 +90,49 @@ public class RoadService { ...@@ -80,6 +90,49 @@ public class RoadService {
return roadMapper.queryRoads(cmptId); return roadMapper.queryRoads(cmptId);
} }
/**
* 获取组别(多路线支持)
* @param cmptId
* @return
*/
public List<Road> queryRoadsMultiPath(Integer cmptId) {
log.info("===== queryRoadsMultiPath -> RoadService enter");
List<Road> roads = remoteService.getRoads(cmptId);
if(roads == null) {
return null;
}
for (Road road : roads) {
log.info("RoadService api接口 getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName() + " getFileUrl:" + road.getFileUrl());
}
List<Road> localRoads = roadMapper.queryRoadsMultiPath(cmptId);
for (Road road : localRoads) {
log.info("RoadService 数据库接口 getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName() + " getFileUrl:" + road.getFileUrl());
}
for (Road road : roads) { // 更新 插入操作
if (localRoads.contains(road)) {
Road rd = localRoads.get(localRoads.indexOf(road));
if (!rd.getName().equals(road.getName())) {
rd.setName(road.getName());
roadMapper.update(road);
}
log.info("RoadService contains getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName());
} else {
roadMapper.save(road);
log.info("RoadService not contains getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName());
}
}
for (Road road : localRoads) { // 删除操作
if (!roads.contains(road)) {
roadMapper.delete(road.getRoadId());
}
}
for (Road road : localRoads) {
log.info("RoadService 接口和api更新后数据 getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName() + " getFileUrl:" + road.getFileUrl());
}
return roadMapper.queryRoadsMultiPath(cmptId);
}
/** /**
* 将gps文件转化为json文件 * 将gps文件转化为json文件
* @param url * @param url
......
package com.dlbridge.jadp.plugins.cmpt.utils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class StaticFieldHolder {
/**导入成绩数据标示*/
public static final String IMPORT_SCORE_DATA = "importScoreData";
public static Map<String, SoftReference<XSSFWorkbook>> resultFile = new ConcurrentHashMap<>();
}
...@@ -38,8 +38,8 @@ public class CmptScoreRuleScoreInfoController { ...@@ -38,8 +38,8 @@ public class CmptScoreRuleScoreInfoController {
*/ */
@RequestMapping("getCmptScoreRuleScoreInfo") @RequestMapping("getCmptScoreRuleScoreInfo")
@ResponseBody @ResponseBody
public Page<List<CmptScoreRuleScoreInfo>> getCmptScoreRuleScoreInfo(Pageable page, int cmptId, int roadId,int ruleId,int checkstatus) { public Page<List<CmptScoreRuleScoreInfo>> getCmptScoreRuleScoreInfo(Pageable page, int cmptId, int roadId, int pathId, int ruleId,int checkstatus) {
Page<List<CmptScoreRuleScoreInfo>> result = cmptScoreRuleScoreInfoService.getCmptScoreRuleScoreInfo(page,cmptId,roadId,ruleId,checkstatus); Page<List<CmptScoreRuleScoreInfo>> result = cmptScoreRuleScoreInfoService.getCmptScoreRuleScoreInfo(page,cmptId,roadId,pathId,ruleId,checkstatus);
result.setCode(200); result.setCode(200);
return result; return result;
} }
...@@ -56,7 +56,7 @@ public class CmptScoreRuleScoreInfoController { ...@@ -56,7 +56,7 @@ public class CmptScoreRuleScoreInfoController {
public Result uploadCmptScoreRuleScoreInfo(int cmptId, int roadId, int ruleId, int[] noPassedIds, int[] passedIds){ public Result uploadCmptScoreRuleScoreInfo(int cmptId, int roadId, int ruleId, int[] noPassedIds, int[] passedIds){
boolean isOk= cmptScoreRuleScoreInfoService.uploadCmptScoreRuleScoreInfo(cmptId,roadId,ruleId,noPassedIds,passedIds); boolean isOk= cmptScoreRuleScoreInfoService.uploadCmptScoreRuleScoreInfo(cmptId,roadId,ruleId,noPassedIds,passedIds);
log.info("审核成绩"+isOk); log.info("审核成绩"+isOk);
return new Result().success(); return Result.success();
} }
/** /**
...@@ -68,9 +68,9 @@ public class CmptScoreRuleScoreInfoController { ...@@ -68,9 +68,9 @@ public class CmptScoreRuleScoreInfoController {
*/ */
@RequestMapping("getCmptScoreRuleScoreInfoStatistics") @RequestMapping("getCmptScoreRuleScoreInfoStatistics")
@ResponseBody @ResponseBody
public Result getCmptScoreRuleScoreInfoStatistics(int cmptId,int roadId,int ruleId){ public Result getCmptScoreRuleScoreInfoStatistics(int cmptId,int roadId,int ruleId,int pathId){
HashMap<String,Object> resultList=cmptScoreRuleScoreInfoService.getCmptScoreRuleScoreInfoStatistics(cmptId,roadId,ruleId); HashMap<String,Object> resultList=cmptScoreRuleScoreInfoService.getCmptScoreRuleScoreInfoStatistics(cmptId,roadId,ruleId,pathId);
return new Result().success().setContent(resultList); return Result.success().setContent(resultList);
} }
......
...@@ -50,7 +50,7 @@ public class RoadController { ...@@ -50,7 +50,7 @@ public class RoadController {
public ModelAndView index(@PathVariable("cmptId") Integer cmptId, ModelAndView mv) { public ModelAndView index(@PathVariable("cmptId") Integer cmptId, ModelAndView mv) {
Cmpt cmpt = cmptService.queryCmptBycmptId(cmptId); Cmpt cmpt = cmptService.queryCmptBycmptId(cmptId);
mv.addObject("cmpt", cmpt); mv.addObject("cmpt", cmpt);
List<Road> list = roadService.queryRoads(cmptId); List<Road> list = roadService.queryRoadsMultiPath(cmptId);
if(list != null){ if(list != null){
for (Road road : list) { for (Road road : list) {
log.info("RoadController getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName()); log.info("RoadController getName:" + road.getName() + " getRoadId:" + road.getRoadId() + " getFileName:" + road.getFileName());
......
...@@ -66,11 +66,11 @@ public class RoadsGpsCheckpointController { ...@@ -66,11 +66,11 @@ public class RoadsGpsCheckpointController {
* @param roadId * @param roadId
* @return * @return
*/ */
@RequestMapping("getGpsCheckPointByRoadId/{cmptId}/{roadId}") @RequestMapping("getGpsCheckPointByRoadId/{cmptId}/{roadId}/{pathId}")
@ResponseBody @ResponseBody
public Result getGpsCheckPointByRoadId(@PathVariable("cmptId") Integer cmptId, public Result getGpsCheckPointByRoadId(@PathVariable("cmptId") Integer cmptId,
@PathVariable("roadId") Integer roadId, @PathVariable("roadId") Integer roadId,
@RequestParam(name = "pathId", required = false, defaultValue = "-1") int pathId) { @PathVariable("pathId") Integer pathId) {
RoadGpsPoint roadGpsPoint = roadService.getGps(roadId, pathId); RoadGpsPoint roadGpsPoint = roadService.getGps(roadId, pathId);
if(roadGpsPoint == null) {return Result.fail().setMsg("未设置轨迹");} if(roadGpsPoint == null) {return Result.fail().setMsg("未设置轨迹");}
String points = roadGpsPoint.getPoints(); String points = roadGpsPoint.getPoints();
......
...@@ -57,19 +57,18 @@ public class ScanController { ...@@ -57,19 +57,18 @@ public class ScanController {
@PageView @PageView
public ModelAndView index(@PathVariable("cmptId") Integer cmptId, ModelAndView mv) { public ModelAndView index(@PathVariable("cmptId") Integer cmptId, ModelAndView mv) {
Cmpt cmpt = cmptService.queryCmptBycmptId(cmptId); Cmpt cmpt = cmptService.queryCmptBycmptId(cmptId);
List<Road> roads = remoteService.getRoads(cmptId); // List<Road> roads = remoteService.getRoads(cmptId);
mv.setViewName("cmpt/scan"); mv.setViewName("cmpt/scan");
mv.addObject("cmpt", cmpt); mv.addObject("cmpt", cmpt);
mv.addObject("roads", roads);
//int count = geexekScoreService.hasCheckPoint(cmptId); // Linc 多路线情况修正 2023/01/29
// TODO Linc 多路线情况
List<Map> map = geexekScoreService.getRoadCheckPointMap(cmptId); List<Map> map = geexekScoreService.getRoadCheckPointMap(cmptId);
mv.addObject("hasCps", map.size() > 0); mv.addObject("hasCps", map.size() > 0);
mv.addObject("roads", map);
log.info("=====gk/scan/index/,roads:{}",map);
Map<Integer,Integer> result = new HashMap<>(); Map<Integer,Integer> result = new HashMap<>();
for(Map m : map){ for(Map m : map){
result.put(Integer.valueOf(m.get("road_id")+""),Integer.valueOf(m.get("number")+"")); result.put(Integer.valueOf(m.get("pathId")+""),Integer.valueOf(m.get("number")+""));
} }
mv.addObject("cpMap", result); mv.addObject("cpMap", result);
return mv; return mv;
...@@ -90,10 +89,10 @@ public class ScanController { ...@@ -90,10 +89,10 @@ public class ScanController {
* @throws IOException * @throws IOException
* @throws Exception * @throws Exception
*/ */
@GetMapping("downLoadAllQRByRoadId/{cmptId}/{roadId}") @GetMapping("downLoadAllQRByRoadId/{cmptId}/{roadId}/{pathId}")
public void downLoadAllQRByRoadId(@PathVariable("cmptId") int cmptId, public void downLoadAllQRByRoadId(@PathVariable("cmptId") int cmptId,
@PathVariable("roadId") int roadId, @PathVariable("roadId") int roadId,
@RequestParam(name = "pathId", required = false, defaultValue = "-1") int pathId, @PathVariable("pathId") int pathId,
HttpServletResponse httpServletResponse) { HttpServletResponse httpServletResponse) {
//获取项目的名字 //获取项目的名字
HashMap<String, Object> roadinfo = remoteService.getRoadinfoByroadId(cmptId, roadId); HashMap<String, Object> roadinfo = remoteService.getRoadinfoByroadId(cmptId, roadId);
......
...@@ -3,22 +3,35 @@ package com.dlbridge.jadp.plugins.cmpt.web; ...@@ -3,22 +3,35 @@ package com.dlbridge.jadp.plugins.cmpt.web;
import com.dlbridge.jadp.common.interceptor.PageView; import com.dlbridge.jadp.common.interceptor.PageView;
import com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRule; import com.dlbridge.jadp.plugins.cmpt.bean.CmptScoreRule;
import com.dlbridge.jadp.plugins.cmpt.bean.FuncSetting; import com.dlbridge.jadp.plugins.cmpt.bean.FuncSetting;
import com.dlbridge.jadp.plugins.cmpt.bean.Path;
import com.dlbridge.jadp.plugins.cmpt.bean.Road; import com.dlbridge.jadp.plugins.cmpt.bean.Road;
import com.dlbridge.jadp.plugins.cmpt.dao.model.Cmpt; import com.dlbridge.jadp.plugins.cmpt.dao.model.Cmpt;
import com.dlbridge.jadp.plugins.cmpt.service.CmptScoreRuleService; import com.dlbridge.jadp.plugins.cmpt.service.CmptScoreRuleService;
import com.dlbridge.jadp.plugins.cmpt.service.CmptService; import com.dlbridge.jadp.plugins.cmpt.service.CmptService;
import com.dlbridge.jadp.plugins.cmpt.service.FuncSettingService; import com.dlbridge.jadp.plugins.cmpt.service.FuncSettingService;
import com.dlbridge.jadp.plugins.cmpt.service.RoadService; import com.dlbridge.jadp.plugins.cmpt.service.RoadService;
import com.dlbridge.jadp.plugins.cmpt.utils.StaticFieldHolder;
import com.neusoft.www.utils.web.Result; import com.neusoft.www.utils.web.Result;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -60,6 +73,21 @@ public class ScoreReviewController { ...@@ -60,6 +73,21 @@ public class ScoreReviewController {
return Result.success().setContent(list); return Result.success().setContent(list);
} }
@RequestMapping("paths/{cmptId}/{roadId}")
@ResponseBody
public Result paths(@PathVariable("cmptId") Integer cmptId,@PathVariable("roadId") Integer roadId, ModelAndView mv) {
List<Path> list = roadService.queryPaths(cmptId, roadId);
List<Path> pathList = new ArrayList<>();
Path pa = new Path();
pa.setPathId(-1);
pa.setPathName("全部");
pathList.add(pa);
for(Path p : list){
pathList.add(p);
}
return Result.success().setContent(pathList);
}
@RequestMapping("rules/{cmptId}") @RequestMapping("rules/{cmptId}")
@ResponseBody @ResponseBody
public Result rules(@PathVariable("cmptId") Integer cmptId, ModelAndView mv) { public Result rules(@PathVariable("cmptId") Integer cmptId, ModelAndView mv) {
...@@ -67,6 +95,60 @@ public class ScoreReviewController { ...@@ -67,6 +95,60 @@ public class ScoreReviewController {
return Result.success().setContent(cmptScoreRules); return Result.success().setContent(cmptScoreRules);
} }
@RequestMapping("importScore")
@ResponseBody
public Result importScoreExcel(@RequestParam("file") MultipartFile file,
@RequestParam(name = "mark", required = true) String mark,
@RequestParam(name = "cmptId", required = true) Integer cmptId,
@RequestParam(name = "roadId", required = true) Integer roadId,
@RequestParam(name = "pathId", required = false, defaultValue = "-1") Integer pathId,
HttpServletRequest req, HttpServletResponse response) throws IOException {
if (file == null) {
return null;
}
log.info(file.getOriginalFilename());
String name = file.getOriginalFilename();// 获取上传文件名,包括路径
long size = file.getSize();
if ((name == null || name.equals("")) && size == 0) {
return null;
}
InputStream in = file.getInputStream();
try {
XSSFWorkbook workbook = new XSSFWorkbook(in);
Result result = cmptScoreRuleService.importScoreExcel(workbook, cmptId, roadId, pathId);
if (!result.status) {
SoftReference<XSSFWorkbook> sr = new SoftReference(workbook);
StaticFieldHolder.resultFile.put(StaticFieldHolder.IMPORT_SCORE_DATA + mark, sr);
return Result.fail().setMsg("导入成绩失败,详情请下载错误文件!");
}
return result;
} catch (Exception e) {
return Result.fail().setMsg("导入成绩Excel异常!");
}
}
@RequestMapping("downloadImportResultExcel")
public Result downloadImportResultExcel(HttpServletRequest request, HttpServletResponse response) throws Exception {
String mark = request.getParameter("mark");
String operation = request.getParameter("operation");
try (OutputStream outputStream = response.getOutputStream();) {
String resultFileKey = operation + mark;
SoftReference<XSSFWorkbook> softReference = StaticFieldHolder.resultFile.get(resultFileKey);
XSSFWorkbook workbook = softReference.get();
String exportFileName = operation + mark + ".xlsx";
response.setContentType("text/html;charset=utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + exportFileName);
workbook.write(outputStream);
// remove the result file
StaticFieldHolder.resultFile.remove(resultFileKey);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
} }
...@@ -125,10 +125,11 @@ ...@@ -125,10 +125,11 @@
<div class="data"> <div class="data">
<label for="">项目</label> <label for="">项目</label>
<c:forEach var="item" items="${roads}" varStatus="idx"> <c:forEach var="item" items="${roads}" varStatus="idx">
<div class="road-name ${idx.index==0?'active':''}" road-id="${item.roadId}"> <div class="road-name ${idx.index==0?'active':''}" path-id="${item.pathId}" road-id="${item.roadId}">
<input type="hidden" id="roadId" name="roadId" value="${item.roadId}"> <input type="hidden" id="roadId" name="roadId" value="${item.roadId}">
<span class="road-text">${item.name}</span> <input type="hidden" id="pathId" name="pathId" value="${item.pathId}">
<span class="down QRCodeDown" style="${cpMap.get(item.roadId) > 0 ? '':'color: #999'}" data-hasCp="${cpMap.get(item.roadId) > 0}">下载全部二维码</span> <span class="road-text">${item.pathName}</span>
<span class="down QRCodeDown" style="${cpMap.get(item.pathId) > 0 ? '':'color: #999'}" data-hasCp="${cpMap.get(item.pathId) > 0}">下载全部二维码</span>
</div> </div>
</c:forEach> </c:forEach>
</div> </div>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<%@ include file="/WEB-INF/views/include/taglib.jsp" %> <%@ include file="/WEB-INF/views/include/taglib.jsp" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="jaaproot" value="${pageContext.request.contextPath}"/>
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
...@@ -31,8 +32,8 @@ ...@@ -31,8 +32,8 @@
<link rel="stylesheet" href="${ctxStatic}/cmpt/score_review.css?<%=System.currentTimeMillis()%>"/> <link rel="stylesheet" href="${ctxStatic}/cmpt/score_review.css?<%=System.currentTimeMillis()%>"/>
<script src="${ctxStatic}/My97DatePicker/WdatePicker.js" type="text/javascript"></script> <script src="${ctxStatic}/My97DatePicker/WdatePicker.js" type="text/javascript"></script>
<script src="${ctxStatic}/newdermon/vendor/jquery/jquery.min.js"></script> <script src="${ctxStatic}/newdermon/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="${ctxStatic}/layer/layer.js"></script> <script type="text/javascript" charset="utf-8" src="${ctxStatic}/layerImport/layer.js"></script>
<link rel="stylesheet" href="${ctxStatic}/layer/skin/layer.css"> <link rel="stylesheet" href="${ctxStatic}/layerImport/need/layer.css">
<link rel="stylesheet" href="/static/cmpt/score.css?<%=System.currentTimeMillis()%>"> <link rel="stylesheet" href="/static/cmpt/score.css?<%=System.currentTimeMillis()%>">
<style> <style>
.img-item video{ .img-item video{
...@@ -80,18 +81,11 @@ ...@@ -80,18 +81,11 @@
<div class="flex-vt"> <div class="flex-vt">
<span class="title">审核结果</span> <span class="title">审核结果</span>
<span class="export-btn">导出名单</span> <span class="export-btn">导出名单</span>
<span class="import-score-btn" >导入成绩</span>
<input type="file" name="file" style="display: none" id="import-btn">
</div> </div>
<div class="flex" style="margin: 20px 0px 0px 0px"> <div class="flex" style="margin: 20px 0px 0px 0px">
<div class="flex-vt select-section">
<label>项目</label>
<div style="position: relative;">
<select v-on:change="changeRoad" v-model="selectedRoadId" class="select" name="">
<option v-for="road in roads" v-text="road.name" :value="road.roadId" :data-roadId="road.roadId"></option>
</select>
<span class="down-arrow"></span>
</div>
</div>
<div class="flex-vt select-section"> <div class="flex-vt select-section">
<label style="width: 100px;">成绩记录方式</label> <label style="width: 100px;">成绩记录方式</label>
<div style="position: relative; width: 136px;"> <div style="position: relative; width: 136px;">
...@@ -112,6 +106,27 @@ ...@@ -112,6 +106,27 @@
</div> </div>
</div> </div>
<div class="flex" style="margin: 20px 0px 0px 0px">
<div class="flex-vt select-section">
<label>项目</label>
<div style="position: relative;">
<select v-on:change="changeRoad" v-model="selectedRoadId" class="select" name="">
<option v-for="road in roads" v-text="road.name" :value="road.roadId" :data-roadId="road.roadId"></option>
</select>
<span class="down-arrow"></span>
</div>
</div>
<div class="flex-vt select-section" >
<label>路线</label>
<div style="position: relative;">
<select v-on:change="changePath" v-model="selectedPathId" class="select" name="">
<option v-for="path in paths" v-text="path.pathName" :value="path.pathId" :data-roadId="path.pathId"></option>
</select>
<span class="down-arrow"></span>
</div>
</div>
</div>
<div class="tab"> <div class="tab">
<div class="flex"> <div class="flex">
<span :class="['review-status',reviewStatus==0?'active':'']" v-on:click="changeStatus(0)" >待审核(<span v-text="reviewCount.waiting"></span>)</span> <span :class="['review-status',reviewStatus==0?'active':'']" v-on:click="changeStatus(0)" >待审核(<span v-text="reviewCount.waiting"></span>)</span>
...@@ -260,9 +275,33 @@ ...@@ -260,9 +275,33 @@
<span v-on:click="closeDialog" class="iconClose"></span> <span v-on:click="closeDialog" class="iconClose"></span>
</div> </div>
</div> </div>
<div class="mask">
<div class="dialog">
<h3>成绩导入</h3>
<div style="margin: 70px 0px 0px 0px;text-align: right;">
<span class="btn cancel" style="margin-right: 30px">取消</span>
<a class="btn" href="${jaaproot}/static/nameListFile/score_import_template.xlsx" download="成绩导入模板"> 下载模板 </a>
<span class="btn sure" v-on:click="importList()">导入</span>
</div>
</div>
</div>
<div class="maskErr">
<div class="dialog">
<h3>错误文件下载</h3>
<div style="margin: 70px 0px 0px 0px;text-align: right;">
<span class="btn cancel" id="errCancel" style="margin-right: 30px">取消</span>
<span class="btn sure" id="errorDetail">文件下载</span>
</div>
</div>
</div>
</div> </div>
</div> </div>
<script src="${ctxStatic}/vue/vue.js"></script> <script src="${ctxStatic}/vue/vue.js"></script>
<script src="${ctxStatic}/upload/vendor/jquery.ui.widget.js"></script>
<script src="${ctxStatic}/upload/jquery.fileupload.js"></script>
<script src="${ctxStatic}/newdermon/vendor/popper.js/umd/popper.min.js"></script> <script src="${ctxStatic}/newdermon/vendor/popper.js/umd/popper.min.js"></script>
<script src="${ctxStatic}/js/qikoo.js"></script> <script src="${ctxStatic}/js/qikoo.js"></script>
......
...@@ -246,6 +246,16 @@ label{ ...@@ -246,6 +246,16 @@ label{
z-index: 99; z-index: 99;
display: none; display: none;
} }
.maskErr{
width: 100%;
height: 100%;
position: fixed;
left: 0px;
top: 0px;
background: rgba(0,0,0,0.3);
z-index: 99;
display: none;
}
.dialog{ .dialog{
padding: 30px 40px; padding: 30px 40px;
height: 300px; height: 300px;
...@@ -288,6 +298,7 @@ label{ ...@@ -288,6 +298,7 @@ label{
height:42px; height:42px;
background:rgba(206,57,57,1); background:rgba(206,57,57,1);
border-radius:4px; border-radius:4px;
margin-left: 20px;
} }
.extra-item{ .extra-item{
height: 80px; height: 80px;
......
...@@ -383,6 +383,17 @@ input.score-input-bigger{ ...@@ -383,6 +383,17 @@ input.score-input-bigger{
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
} }
.import-score-btn{
width:145px;
height:40px;
background: rgba(206,57,57,1);
border-radius: 4px;
font-size: 16px;
color: white;
line-height: 40px;
text-align: center;
cursor: pointer;
}
.pass-icon{ .pass-icon{
background: url("/static/images/manage/score_pass.png") center no-repeat; background: url("/static/images/manage/score_pass.png") center no-repeat;
background-size: contain; background-size: contain;
......
$(document).ready(function () { $(document).ready(function () {
//切换项目,获取不同计时的打卡点 //切换项目,获取不同计时的打卡点
var roadId = $('.road-name').first().attr('road-id'); var roadId = $('.road-name').first().attr('road-id');
getTimeCp(roadId); var pathId = $('.road-name').first().attr('path-id');
getTimeCp(roadId,pathId);
//获取gpx路线上的打卡点 //获取gpx路线上的打卡点
//初始化已经配置好的GPS计时点配置列表 //初始化已经配置好的GPS计时点配置列表
...@@ -64,10 +65,11 @@ $(document).ready(function () { ...@@ -64,10 +65,11 @@ $(document).ready(function () {
var hasCp = $(this).attr('data-hasCp'); var hasCp = $(this).attr('data-hasCp');
if(hasCp == 'false') return; if(hasCp == 'false') return;
var roadId = $(this).parent().attr('road-id'); var roadId = $(this).parent().attr('road-id');
var pathId = $(this).parent().attr('path-id');
console.log(roadId); console.log(roadId);
const link = document.createElement('a') const link = document.createElement('a')
const body = document.querySelector('body') const body = document.querySelector('body')
link.href = "/gk/scan/downLoadAllQRByRoadId/"+getCId()+"/"+roadId link.href = "/gk/scan/downLoadAllQRByRoadId/"+getCId()+"/"+roadId+"/"+pathId
// fix Firefox // fix Firefox
link.style.display = 'none' link.style.display = 'none'
body.appendChild(link) body.appendChild(link)
...@@ -111,7 +113,7 @@ function getCpGpsList(roadId) { ...@@ -111,7 +113,7 @@ function getCpGpsList(roadId) {
* 获取计时的打卡点 * 获取计时的打卡点
* @param roadId * @param roadId
*/ */
function getTimeCp(roadId) { function getTimeCp(roadId,pathId) {
$('tbody').empty() $('tbody').empty()
$.ajax({ $.ajax({
url : '/gk/roadGpsCheckpoint/getTimeCheckpointByRoadId/'+getCId()+"/"+roadId, url : '/gk/roadGpsCheckpoint/getTimeCheckpointByRoadId/'+getCId()+"/"+roadId,
...@@ -131,7 +133,7 @@ function getTimeCp(roadId) { ...@@ -131,7 +133,7 @@ function getTimeCp(roadId) {
' <td>'+Number(e.checkpointLatitude == null? "0" : e.checkpointLatitude).toFixed(6)+','+Number(e.checkpointLongitude==null?"0":e.checkpointLongitude).toFixed(6)+'</td>\n' + ' <td>'+Number(e.checkpointLatitude == null? "0" : e.checkpointLatitude).toFixed(6)+','+Number(e.checkpointLongitude==null?"0":e.checkpointLongitude).toFixed(6)+'</td>\n' +
' </tr>'); ' </tr>');
}) })
getGpsCp(roadId); getGpsCp(roadId,pathId);
} }
} }
}) })
...@@ -143,9 +145,9 @@ function getTimeCp(roadId) { ...@@ -143,9 +145,9 @@ function getTimeCp(roadId) {
* 获取路线上的打卡点 * 获取路线上的打卡点
* @param roadId * @param roadId
*/ */
function getGpsCp(roadId) { function getGpsCp(roadId,pathId) {
$.ajax({ $.ajax({
url : '/gk/roadGpsCheckpoint/getGpsCheckPointByRoadId/'+getCId()+"/"+roadId, url : '/gk/roadGpsCheckpoint/getGpsCheckPointByRoadId/'+getCId()+"/"+roadId+"/"+pathId,
success:function (data) { success:function (data) {
if(data.status){ if(data.status){
$('.load').show(); $('.load').show();
......
...@@ -2,6 +2,7 @@ var score = new Vue({ ...@@ -2,6 +2,7 @@ var score = new Vue({
el : '#score', el : '#score',
data : { data : {
selectedRoadId:-1, selectedRoadId:-1,
selectedPathId:-1,
selectedOrigin:1, selectedOrigin:1,
searchWord:"", searchWord:"",
param:{ param:{
...@@ -27,8 +28,10 @@ var score = new Vue({ ...@@ -27,8 +28,10 @@ var score = new Vue({
dialog: false, dialog: false,
totalPage:0, totalPage:0,
roads: [], roads: [],
paths: [],
rules: [], rules: [],
scores: [] scores: [],
mark: ""
}, },
filters: { filters: {
substr:function(value,length){ substr:function(value,length){
...@@ -100,6 +103,11 @@ var score = new Vue({ ...@@ -100,6 +103,11 @@ var score = new Vue({
score.$data.param.page = 0; score.$data.param.page = 0;
reviewPage.reloadPage(); reviewPage.reloadPage();
}, },
changePath:function () {
score.$data.jumpToPage = 1;
score.$data.param.page = 0;
reviewPage.reloadPage();
},
searchKd:function () { searchKd:function () {
score.$data.jumpToPage = 1; score.$data.jumpToPage = 1;
score.$data.param.page = 0; score.$data.param.page = 0;
...@@ -110,6 +118,9 @@ var score = new Vue({ ...@@ -110,6 +118,9 @@ var score = new Vue({
score.$data.param.page = 0; score.$data.param.page = 0;
reviewPage.reloadPage(); reviewPage.reloadPage();
}, },
importList:function () {
$("#import-btn").trigger("click");
},
next:function () { next:function () {
if((score.$data.param.page+2) > Math.ceil(score.$data.totalPage/10)){ if((score.$data.param.page+2) > Math.ceil(score.$data.totalPage/10)){
layer.alert('已经是最后一页!'); layer.alert('已经是最后一页!');
...@@ -256,6 +267,19 @@ var reviewPage = { ...@@ -256,6 +267,19 @@ var reviewPage = {
if(data.status == 1){ if(data.status == 1){
score.$data.roads = data.content; score.$data.roads = data.content;
score.$data.selectedRoadId = score.$data.roads[0].roadId; score.$data.selectedRoadId = score.$data.roads[0].roadId;
reviewPage.getPaths();
reviewPage.reloadPage();
}
}
});
},
getPaths:function () {
$.ajax({
url:"/gk/review/paths/"+getCId()+"/"+score.$data.selectedRoadId,
success:function (data) {
if(data.status == 1){
score.$data.paths = data.content;
score.$data.selectedPathId = score.$data.paths[0].pathId;
reviewPage.reloadPage(); reviewPage.reloadPage();
} }
} }
...@@ -275,6 +299,7 @@ var reviewPage = { ...@@ -275,6 +299,7 @@ var reviewPage = {
}, },
reloadPage:function () { reloadPage:function () {
score.$data.param.roadId = score.$data.selectedRoadId; score.$data.param.roadId = score.$data.selectedRoadId;
score.$data.param.pathId = score.$data.selectedPathId;
score.$data.param.origin = score.$data.selectedOrigin; score.$data.param.origin = score.$data.selectedOrigin;
score.$data.param.keyword = score.$data.searchWord; score.$data.param.keyword = score.$data.searchWord;
$.ajax({ $.ajax({
...@@ -282,7 +307,7 @@ var reviewPage = { ...@@ -282,7 +307,7 @@ var reviewPage = {
data:score.$data.param, data:score.$data.param,
type:'post', type:'post',
beforeSend:function(){ beforeSend:function(){
layer.load(); //layer.load();
}, },
success:function (data) { success:function (data) {
if(data.code == 200){ if(data.code == 200){
...@@ -315,7 +340,7 @@ var reviewPage = { ...@@ -315,7 +340,7 @@ var reviewPage = {
getStatistic:function(){ getStatistic:function(){
$.ajax({ $.ajax({
url : '/geexekscore/api/v1/cmpt-score-rule-scoreinfo/getCmptScoreRuleScoreInfoStatistics?cmptId='+getCId()+'&roadId='+ url : '/geexekscore/api/v1/cmpt-score-rule-scoreinfo/getCmptScoreRuleScoreInfoStatistics?cmptId='+getCId()+'&roadId='+
score.$data.selectedRoadId score.$data.selectedRoadId + "&pathId=" + score.$data.selectedPathId
+'&origin='+ score.$data.selectedOrigin+"&keyword="+score.$data.searchWord, +'&origin='+ score.$data.selectedOrigin+"&keyword="+score.$data.searchWord,
type:'post', type:'post',
success:function (data) { success:function (data) {
...@@ -365,6 +390,80 @@ var reviewPage = { ...@@ -365,6 +390,80 @@ var reviewPage = {
}) })
} }
} }
var _upload={
//成绩导入
xls:function(){
var uploadIndex=0;
var jqXHR =null;
score.$data.mark = new Date().getTime();
$('body').on('click','#import-btn',function(e){
var url = "/gk/review/importScore?cmptId="+getCId()+"&roadId="+score.$data.selectedRoadId+"&pathId="+score.$data.selectedPathId+"&mark="+score.$data.mark;
jqXHR = $(this).fileupload({
url: url,
dataType: 'json',
add: function (e, data) {
var files=data.files;
if (files.length > 1) {
layer.error('只能上传一个excel');
return false;
}
if (files.length <= 0) {
layer.error("请选择上传的excel");
return false;
}
if (files.length == 1) {
var picFile = files[0];
var fileSize = Math.round(picFile.size / 1024);// kB
if (fileSize > 7*1024) {
layer.error("excel必须小于7MB");
return false;
}
var jqXHR =data.submit();
layer.waiting("名单导入过程中,请耐心等待...");
uploadIndex=layer.upload("正在上传excel,请等待...",jqXHR);
}
},
done: function (e, data) {
layer.closeAll();
layer.info("文件上传成功");
if(data.result.status){
$('.mask').fadeOut();
return ;
}else{
layer.alert(data.result.msg);
$('.mask').fadeOut();
$('.maskErr').fadeIn();
return ;
}
},
fail:function (jqXHR, textStatus) {
if (textStatus.textStatus === 'abort') {
layer.close(uploadIndex);
return;
}
layer.closeAll();
layer.error("上传excel失败");
return false;
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
if(progress==100){
layer.close(uploadIndex);
}
}
});
});
return jqXHR;
}
};
$(document).ready(function () { $(document).ready(function () {
$('body').on('click', '.status', function () { $('body').on('click', '.status', function () {
var checked = $(this).hasClass('checked'); var checked = $(this).hasClass('checked');
...@@ -390,7 +489,33 @@ $(document).ready(function () { ...@@ -390,7 +489,33 @@ $(document).ready(function () {
$('.export-btn').click(function () { $('.export-btn').click(function () {
window.open("/geexekscore/api/v1/cmpt-score-rank/export/"+getCId()) window.open("/geexekscore/api/v1/cmpt-score-rank/export/"+getCId())
}) })
$('.export-btn').click(function () {
window.open("/geexekscore/api/v1/cmpt-score-rank/export/"+getCId())
})
$('.import-score-btn').click(function () {
$('.mask').fadeIn();
});
$('.cancel').click(function () {
$('.mask').fadeOut();
$('.dialog').removeAttr('data-id');
$('.dialog').removeAttr('data-type');
})
$('#errCancel').click(function () {
$('.maskErr').fadeOut();
})
//下载详细信息excel
$('body').on('click','#errorDetail',function(e){
// window.location.href = '/gk/review/downloadImportResultExcel?operation=importScoreData&mark='+score.$data.mark;
var url = '/gk/review/downloadImportResultExcel?operation=importScoreData&mark='+score.$data.mark;
window.open(url);
});
reviewPage.getRoads(); reviewPage.getRoads();
_upload.xls();
}); });
function calculateScore(){ function calculateScore(){
var scoreId = $($dp.el).parents('.score-detail').attr('scoreId') var scoreId = $($dp.el).parents('.score-detail').attr('scoreId')
......
/*!
@Name:layer mobile v1.6 弹层组件移动版
@Author:贤心
@Date:2015-07-08
@Copyright:Sentsin Xu(贤心)
@官网:http://layer.layui.com/mobile/
@License:MIT
*/
;
!function (win) {
"use strict";
var doc = document, query = 'querySelectorAll', claname = 'getElementsByClassName', S = function (s) {
return doc[query](s);
};
//默认配置
var config = {
type: 0,
shade: true,
shadeClose: true,
fixed: true,
anim: true,
animClass: "layermanim"
};
win.ready = {
extend: function (obj) {
var newobj = JSON.parse(JSON.stringify(config));
for (var i in obj) {
newobj[i] = obj[i];
}
return newobj;
},
timer: {},
end: {}
};
//点触事件
ready.touch = function (elem, fn) {
var move;
elem.addEventListener('touchmove', function () {
move = true;
}, false);
elem.addEventListener('touchend', function (e) {
e.preventDefault();
move || fn.call(this, e);
move = false;
}, false);
};
var index = 0, classs = ['layermbox'], Layer = function (options) {
var that = this;
that.config = ready.extend(options);
that.view();
};
Layer.prototype.view = function () {
var that = this, config = that.config, layerbox = doc.createElement('div');
that.id = layerbox.id = classs[0] + index;
layerbox.setAttribute('class', classs[0] + ' ' + classs[0] + (config.type || 0));
layerbox.setAttribute('index', index);
var title = (function () {
var titype = typeof config.title === 'object';
return config.title
? '<h3 style="' + (titype ? config.title[1] : '') + '">' + (titype ? config.title[0] : config.title) + '</h3><button class="layermend"></button>'
: '';
}());
var button = (function () {
var btns = (config.btn || []).length, btndom;
if (btns === 0 || !config.btn) {
return '';
}
btndom = '<span type="1">' + config.btn[0] + '</span>'
if (btns === 2) {
btndom = '<span type="0">' + config.btn[1] + '</span>' + btndom;
}
return '<div class="layermbtn">' + btndom + '</div>';
}());
if (!config.fixed) {
config.top = config.hasOwnProperty('top') ? config.top : 100;
config.style = config.style || '';
config.style += ' top:' + ( doc.body.scrollTop + config.top) + 'px';
}
if (config.type === 2) {
config.content = '<i></i><i class="laymloadtwo"></i><i></i><div>' + (config.content || '') + '</div>';
}
layerbox.innerHTML = (config.shade ? '<div ' + (typeof config.shade === 'string' ? 'style="' + config.shade + '"' : '') + ' class="laymshade"></div>' : '')
+ '<div class="layermmain" ' + (!config.fixed ? 'style="position:static;"' : '') + '>'
+ '<div class="section">'
+ '<div class="layermchild ' + (config.className ? config.className : '') + ' ' + ((!config.type && !config.shade) ? 'layermborder ' : '') + (config.anim ? config.animClass : '') + '" ' + ( config.style ? 'style="' + config.style + '"' : '' ) + '>'
+ title
+ '<div class="layermcont">' + config.content + '</div>'
+ button
+ '</div>'
+ '</div>'
+ '</div>';
if (!config.type || config.type === 2) {
var dialogs = doc[claname](classs[0] + config.type), dialen = dialogs.length;
if (dialen >= 1) {
layer.close(dialogs[0].getAttribute('index'))
}
}
$("body").append(layerbox);
//document.body.appendChild(layerbox);
var elem = that.elem = S('#' + that.id)[0];
config.success && config.success(elem);
that.index = index++;
that.action(config, elem);
};
Layer.prototype.action = function (config, elem) {
var that = this;
//自动关闭
if (config.time) {
ready.timer[that.index] = setTimeout(function () {
layer.close(that.index);
}, config.time * 1000);
}
//关闭按钮
if (config.title) {
var end = elem[claname]('layermend')[0], endfn = function () {
config.cancel && config.cancel();
layer.close(that.index);
};
ready.touch(end, endfn);
end.onclick = endfn;
}
//确认取消
var btn = function () {
var type = this.getAttribute('type');
if (type == 0) {
config.no && config.no();
layer.close(that.index);
} else {
config.yes ? config.yes(that.index) : layer.close(that.index);
}
};
if (config.btn) {
var btns = elem[claname]('layermbtn')[0].children, btnlen = btns.length;
for (var ii = 0; ii < btnlen; ii++) {
ready.touch(btns[ii], btn);
btns[ii].onclick = btn;
}
}
//点遮罩关闭
if (config.shade && config.shadeClose) {
var shade = elem[claname]('laymshade')[0];
ready.touch(shade, function () {
layer.close(that.index, config.end);
});
shade.onclick = function () {
layer.close(that.index, config.end);
};
}
config.end && (ready.end[that.index] = config.end);
};
var layer = {
v: '1.6',
index: index,
//核心方法
open: function (options) {
var o = new Layer(options || {});
return o.index;
},
close: function (index) {
var ibox = S('#' + classs[0] + index)[0];
if (!ibox) return;
ibox.innerHTML = '';
doc.body.removeChild(ibox);
clearTimeout(ready.timer[index]);
delete ready.timer[index];
typeof ready.end[index] === 'function' && ready.end[index]();
delete ready.end[index];
},
//关闭所有layer层
closeAll: function () {
var boxs = doc[claname](classs[0]);
for (var i = 0, len = boxs.length; i < len; i++) {
layer.close((boxs[0].getAttribute('index') | 0));
}
},
closeById:function(id){
layer.close($("#"+id).attr("data-index"));
},
//自定义的
wait: function (message) {
var index=layer.open({
type: 2,
content: message
// shadeClose:false
});
return index;
},
//不关闭的
waiting: function (message) {
var index=layer.open({
type: 2,
content: message,
shadeClose: false
});
return index;
},
deng: function (message,id) {
var index=layer.open({
type: 2,
content: message,
shadeClose: false,
success:function(elem){
var index=$(elem).attr("index");
$(elem).find(".layermmain").attr("id",id).attr("data-index",index);
}
});
return index;
},
error: function (message) {
var index=layer.open({
anim: false,
content: message,
btn: ['确认'],
z:99999999,
style: "text-align:center;"
});
return index;
/* var index=layer.open({
type: 1,
content: message,
animClass: 'fadeInDown',
style: 'position:absolute;left:0;top:0px;width:100%;border:none;font-size: 16px;padding: 13px;' +
'background-color: #de4343;border-color: #c43d3d;text-align: center;color: #fff;'
});
return index;*/
},
info: function (message) {
var index=layer.open({
anim: false,
content: message,
shade: false,
style: " padding:0;width:0;border:none;",
z:99999999,
time: 1.6
});
return index;
/* var index=layer.open({
type: 1,
content: message,
time: 2,
animClass: 'fadeInDown',
shade: false,
z:99999999,
style: 'position:absolute;left:0;top:0px;width:100%;border:none;font-size: 16px;padding: 13px;' +
'background-color: #72c246;border-color: #72c246;text-align: center;color: #fff;'
});
return index;*/
},
upload: function (message,jqXHR) {
var html=message+'<a href="javacript:void(0)" class="abort">取消上传</a><div id="progress"><div class="bar" style="width: 0%;height: 18px;background: green;"></div></div>';
var index=layer.open({
type: 1,
content: html,
animClass: 'fadeInDown',
shadeClose: false,
style: 'position:absolute;left:0;top:0px;width:100%;border:none;font-size: 16px;padding: 13px;' +
'background-color: #72c246;border-color: #72c246;text-align: center;color: #fff;',
success:function(elem){
$(elem).find(".abort").click(function(){
jqXHR.abort();
if(typeof _upload!="undefined"&&typeof _upload.uploading!="undefined"){
_upload.uploading=false;
}
})
}
});
return index;
},
down: function (html, success) {
var index=layer.open({
type: 1,
content: html,
animClass: 'fadeInDown',
style: 'position:absolute;left:0;top:0px;width:100%;padding:0px 0 10px;border:none; max-height:80%;overflow:auto;overflow-x: hidden',
success: success
});
return index;
},
up: function (html, success) {
var index=layer.open({
type: 1,
content: html,
animClass: 'fadeInUp',
style: 'position:absolute;left:0;bottom:0;width:100%; padding:10px 0 20px;border:none;max-height:80%;overflow:auto;overflow-x: hidden',
success: success
});
return index;
},
center: function (html, success,shadeClick,shadeClose) {
if(typeof shadeClose=="undefined"){
shadeClose=true;
}
var index=layer.open({
type: 1,
content: html,
animClass:'',
style: 'border-radius: 5px; border:none;',
success: success,
shadeClose: shadeClose,
shadeClick:shadeClick
});
return index;
},
centerNoFix: function (html, success,shadeClick,style) {
if(typeof style=="undefined"){
style="";
}
var index=layer.open({
type: 1,
content: html,
fixed:false,
animClass:'',
style: 'border-radius: 5px; border:none;'+style,
success: success,
shadeClick:shadeClick
});
return index;
},
notify: function (text) {
var index=layer.open({
content: text,
style: "text-align:center;",
time: 1.3
});
return index;
},
alertInfo: function (text) {
var index=layer.open({
anim: false,
content: text,
shade: false,
style: " padding:0;width:0;border:none;",
time: 1.6
});
return index;
},
alert: function (text,callback) {
var index=layer.open({
anim: false,
content: text,
btn: ['确认'],
style: "text-align:center;",
yes:function(){
if (typeof callback != 'undefined') {
callback();
}
layer.close(index);
}
});
return index;
},
confirm: function (text, yesCallback, noCallback) {
var index=layer.open({
anim: false,
content: text,
btn: ['取消', '确定'],
shadeClose: false,
yes: function (index) {
if (typeof noCallback != 'undefined') {
noCallback();
}
layer.close(index);
layer.closeAll();
}, no: function () {
if (typeof yesCallback != 'undefined') {
yesCallback();
}
}
});
return index;
},
down1: function (html, success) {
layer.open({
type: 1,
content: html,
animClass: 'fadeInDown',
style: 'position:absolute;left:0;top:6em;width:100%;padding:0px 0 10px;border:none; max-height:80%;overflow:auto;overflow-x: hidden',
success: success
});
},
alertInfoww: function (text) {
layer.open({
anim: false,
content: '<div class="m_points_windowshow"><div class="m_points_winimg"><img src="../img/gougou.png" alt=""></div><div class="m_points_wininfo"><p class="m_points_winsubm" style="display:block;">报名成功!</p><p class="m_points_windata">积分<span>+5</span></p></div>',
shade: false,
style: "padding:0;width:0;border:none;min-width:0",
time: 300
});
},
alertPointInfo:function (text) {
layer.open({
anim:false,
content: text,
shade:false,
style:"text-align:center;",
time: 1.6
});
},
alertEnrollPoint:function(){
var point='<div class="m_points_windowshow">'+
'<div class="m_points_winimg">'+
'<img src="../../img/gougou.png" alt="">'+
'</div>'+
'<div class="m_points_wininfo">'+
'<p class="m_points_winsubm" style="display:block;">报名成功!</p>'+
'<p class="m_points_windata">积分<span>+5</span></p>'+
'</div> '+
'</div>';
this.alertPointInfo(point);
}
};
'function' === typeof define ? define(function () {
return layer;
}) : win.layer = layer;
}(window);
if(typeof _msgx!="undefined"){
if(_msgx.error!=''){
layer.error(_msgx.error);
}
if(_msgx.info!=''){
layer.info(_msgx.info);
}
}
/* 动画部分 */
/* 默认 */
@-webkit-keyframes bounceIn {
0% {
opacity: 0;
-webkit-transform: scale(.5);
transform: scale(.5)
}
100% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1)
}
}
.layermanim{animation-name: bounceIn; -webkit-animation-name: bounceIn;}
/* 下移 */
@-webkit-keyframes fadeInDown {
0% {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
@keyframes fadeInDown {
0% {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
.fadeInDown {
-webkit-animation-name: fadeInDown;
animation-name: fadeInDown;
}
@-webkit-keyframes fadeInUp {
0% {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
@keyframes fadeInUp {
0% {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
.fadeInUp {
-webkit-animation-name: fadeInUp;
animation-name: fadeInUp;
}
@-webkit-keyframes slideInDown {
0% {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInDown {
0% {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.slideInDown {
-webkit-animation-name: slideInDown;
animation-name: slideInDown;
}
@-webkit-keyframes slideInUp {
0% {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInUp {
0% {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.slideInUp {
-webkit-animation-name: slideInUp;
animation-name: slideInUp;
}
/* layer弹层移动版样式 90000*/
.layermbox{position:absolute; left:0; top:0; width:100%; z-index:998;}
.laymshade,
.layermmain{position:fixed; left:0; top:0; width:100%; height:100%;}
.laymshade{background-color:rgba(0,0,0, .5); pointer-events:auto;}
.layermmain{display:table; font-family: Helvetica, arial, sans-serif; pointer-events: none;}
.layermmain .section{display:table-cell; vertical-align:middle; text-align:center;}
.layermchild{position:relative; display:inline-block; text-align:left; background-color:#fff; font-size:14px; border-radius:6px; box-shadow:0 0 8px rgba(0, 0, 0, 0.1); pointer-events:auto;}
.layermchild{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration: .18s; animation-duration: .18s;}
.layermborder{border:1px solid #999;}
.layermbox0 .layermchild{max-width:260px; min-width:150px;}
.layermbox1 .layermchild{border:none; border-radius:0;}
.layermbox2 .layermchild{width:auto; max-width:260px; min-width:40px; border:none; background-color:rgba(0,0,0,.6); color:#fff;}
.layermchild h3{padding:0 45px 0 10px; height:50px; line-height:50px; border-bottom:1px solid #EBEBEB; font-size:16px; font-weight:400; border-radius:5px 5px 0 0; border-bottom:1px solid #EBEBEB;}
.layermchild h3,
.layermbtn span{ text-overflow:ellipsis; overflow:hidden; white-space:nowrap;}
.layermcont{padding:20px 15px; line-height:22px; border-radius:5px;}
.layermbox1 .layermcont{padding:0;}
.layermbox2 .layermcont{text-align:center; padding:30px 30px 0; line-height: 0;}
.layermbox2 .layermcont i{width:1.5rem; height:1.5rem; margin-left:8px; display:inline-block; background-color:#fff; border-radius:100%;}
.layermbox2 .layermcont i{-webkit-animation: bouncedelay 1.4s infinite ease-in-out; animation: bouncedelay 1.4s infinite ease-in-out; -webkit-animation-fill-mode: both; animation-fill-mode: both;}
@-webkit-keyframes bouncedelay{
0%,80%,100%{-webkit-transform:scale(0)}
40%{-webkit-transform:scale(1)}
}
@keyframes bouncedelay{
0%,80%,100%{transform:scale(0);-webkit-transform:scale(0)}
40%{transform:scale(1);-webkit-transform:scale(1)}
}
.layermbox2 .layermcont i:first-child{margin-left:0; -webkit-animation-delay: -.32s; animation-delay: -.32s;}
.layermbox2 .layermcont i.laymloadtwo{-webkit-animation-delay: -.16s; animation-delay: -.16s;}
.layermbox2 .layermcont>div{line-height:22px; padding-top:7px; margin-bottom:20px; font-size: 14px;}
.layermbtn{position:relative; height:40px; line-height:40px; font-size:0; text-align:center; border-top:1px solid #EBEBEB;}
.layermbtn span{position:relative; display:inline-block; width:50%; text-align:center; font-size:14px; cursor:pointer; border-radius: 0 5px 0 0;}
.layermbtn span:first-child{height:39px; background-color:#fff; border-radius: 0 0 0 5px;}
.layermbtn:before{content:'\20'; position:absolute; width:1px; height:39px; left:50%; top:0; background-color:#EBEBEB;}
.layermend{position:absolute; right:7px; top:10px; width:30px; height:30px; border: 0; font-weight:400; background: transparent; cursor: pointer; -webkit-appearance: none; font-size:30px;}
.layermend::before, .layermend::after{position:absolute; left:5px; top:13px; content:''; width:20px; height:2px; background-color:rgba(0,0,0,.3); transform:rotate(45deg); -webkit-transform:rotate(45deg); border-radius: 3px;}
.layermend::after{transform:rotate(-45deg); -webkit-transform:rotate(-45deg);}
jQuery.extend({
createUploadIframe: function(id, uri)
{
//create frame
var frameId = 'jUploadFrame' + id;
var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"';
if(window.ActiveXObject)
{
if(typeof uri== 'boolean'){
iframeHtml += ' src="' + 'javascript:false' + '"';
}
else if(typeof uri== 'string'){
iframeHtml += ' src="' + uri + '"';
}
}
iframeHtml += ' />';
jQuery(iframeHtml).appendTo(document.body);
return jQuery('#' + frameId).get(0);
},
createUploadForm: function(id, fileElementId, data)
{
//create form
var formId = 'jUploadForm' + id;
var fileId = 'jUploadFile' + id;
var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
if(data)
{
for(var i in data)
{
jQuery('<input type="hidden" name="' + i + '" value="' + data[i] + '" />').appendTo(form);
}
}
var oldElement = jQuery('#' + fileElementId);
var newElement = jQuery(oldElement).clone();
jQuery(oldElement).attr('id', fileId);
jQuery(oldElement).before(newElement);
jQuery(oldElement).appendTo(form);
//set attributes
jQuery(form).css('position', 'absolute');
jQuery(form).css('top', '-1200px');
jQuery(form).css('left', '-1200px');
jQuery(form).appendTo('body');
return form;
},
ajaxFileUpload: function(s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = new Date().getTime()
var form = jQuery.createUploadForm(id, s.fileElementId, (typeof(s.data)=='undefined'?false:s.data));
var io = jQuery.createUploadIframe(id, s.secureuri);
var frameId = 'jUploadFrame' + id;
var formId = 'jUploadForm' + id;
// Watch for a new set of requests
if ( s.global && ! jQuery.active++ )
{
jQuery.event.trigger( "ajaxStart" );
}
var requestDone = false;
// Create the request object
var xml = {}
if ( s.global )
jQuery.event.trigger("ajaxSend", [xml, s]);
// Wait for a response to come back
var uploadCallback = function(isTimeout)
{
var io = document.getElementById(frameId);
try
{
if(io.contentWindow)
{
xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
}else if(io.contentDocument)
{
xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
}
}catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if ( xml || isTimeout == "timeout")
{
requestDone = true;
var status;
try {
status = isTimeout != "timeout" ? "success" : "error";
// Make sure that the request was successful or notmodified
if ( status != "error" )
{
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData( xml, s.dataType );
// If a local callback was specified, fire it and pass it the data
if ( s.success )
s.success( data, status );
// Fire the global callback
if( s.global )
jQuery.event.trigger( "ajaxSuccess", [xml, s] );
} else
jQuery.handleError(s, xml, status);
} catch(e)
{
status = "error";
jQuery.handleError(s, xml, status, e);
}
// The request was completed
if( s.global )
jQuery.event.trigger( "ajaxComplete", [xml, s] );
// Handle the global AJAX counter
if ( s.global && ! --jQuery.active )
jQuery.event.trigger( "ajaxStop" );
// Process result
if ( s.complete )
s.complete(xml, status);
jQuery(io).unbind()
setTimeout(function()
{ try
{
jQuery(io).remove();
jQuery(form).remove();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
}, 100)
xml = null
}
}
// Timeout checker
if ( s.timeout > 0 )
{
setTimeout(function(){
// Check to see if the request is still happening
if( !requestDone ) uploadCallback( "timeout" );
}, s.timeout);
}
try
{
var form = jQuery('#' + formId);
jQuery(form).attr('action', s.url);
jQuery(form).attr('method', 'POST');
jQuery(form).attr('target', frameId);
if(form.encoding)
{
jQuery(form).attr('encoding', 'multipart/form-data');
}
else
{
jQuery(form).attr('enctype', 'multipart/form-data');
}
jQuery(form).submit();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
jQuery('#' + frameId).load(uploadCallback );
return {abort: function () {}};
},
handleError: function( s, xhr, status, e ) {
// If a local callback was specified, fire it
if ( s.error ) {
s.error.call( s.context || s, xhr, status, e );
}
// Fire the global callback
if ( s.global ) {
(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
}
},
uploadHttpData: function( r, type ) {
var data = !type;
data = type == "xml" || data ? r.responseXML : r.responseText;
// If the type is "script", eval it in global context
if ( type == "script" )
jQuery.globalEval( data );
// Get the JavaScript object, if JSON is used.
if ( type == "json" )
// eval( "data = " + data );
data=eval("("+data.replace("<pre>","").replace("</pre>","")+")");
//eval("data = \" "+data+" \" ");
// evaluate scripts within html
if ( type == "html" )
jQuery("<div>").html(data).evalScripts();
return data;
}
})
/*
* jQuery File Upload Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, require, window, document, location, Blob, FormData */
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define([
'jquery',
'jquery.ui.widget'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('./vendor/jquery.ui.widget')
);
} else {
// Browser globals:
factory(window.jQuery);
}
}(function ($) {
'use strict';
// Detect file input support, based on
// http://viljamis.com/blog/2012/file-upload-support-on-mobile/
$.support.fileInput = !(new RegExp(
// Handle devices which give false positives for the feature detection:
'(Android (1\\.[0156]|2\\.[01]))' +
'|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
'|(w(eb)?OSBrowser)|(webOS)' +
'|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
).test(window.navigator.userAgent) ||
// Feature detection for all other devices:
$('<input type="file">').prop('disabled'));
// The FileReader API is not actually used, but works as feature detection,
// as some Safari versions (5?) support XHR file uploads via the FormData API,
// but not non-multipart XHR file uploads.
// window.XMLHttpRequestUpload is not available on IE10, so we check for
// window.ProgressEvent instead to detect XHR2 file upload capability:
$.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);
$.support.xhrFormDataFileUpload = !!window.FormData;
// Detect support for Blob slicing (required for chunked uploads):
$.support.blobSlice = window.Blob && (Blob.prototype.slice ||
Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
// Helper function to create drag handlers for dragover/dragenter/dragleave:
function getDragHandler(type) {
var isDragOver = type === 'dragover';
return function (e) {
e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
var dataTransfer = e.dataTransfer;
if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
this._trigger(
type,
$.Event(type, {delegatedEvent: e})
) !== false) {
e.preventDefault();
if (isDragOver) {
dataTransfer.dropEffect = 'copy';
}
}
};
}
// The fileupload widget listens for change events on file input fields defined
// via fileInput setting and paste or drop events of the given dropZone.
// In addition to the default jQuery Widget methods, the fileupload widget
// exposes the "add" and "send" methods, to add or directly send files using
// the fileupload API.
// By default, files added via file input selection, paste, drag & drop or
// "add" method are uploaded immediately, but it is possible to override
// the "add" callback option to queue file uploads.
$.widget('blueimp.fileupload', {
options: {
// The drop target element(s), by the default the complete document.
// Set to null to disable drag & drop support:
dropZone: $(document),
// The paste target element(s), by the default undefined.
// Set to a DOM node or jQuery object to enable file pasting:
pasteZone: undefined,
// The file input field(s), that are listened to for change events.
// If undefined, it is set to the file input fields inside
// of the widget element on plugin initialization.
// Set to null to disable the change listener.
fileInput: undefined,
// By default, the file input field is replaced with a clone after
// each input field change event. This is required for iframe transport
// queues and allows change events to be fired for the same file
// selection, but can be disabled by setting the following option to false:
replaceFileInput: true,
// The parameter name for the file form data (the request argument name).
// If undefined or empty, the name property of the file input field is
// used, or "files[]" if the file input name property is also empty,
// can be a string or an array of strings:
paramName: undefined,
// By default, each file of a selection is uploaded using an individual
// request for XHR type uploads. Set to false to upload file
// selections in one request each:
singleFileUploads: true,
// To limit the number of files uploaded with one XHR request,
// set the following option to an integer greater than 0:
limitMultiFileUploads: undefined,
// The following option limits the number of files uploaded with one
// XHR request to keep the request size under or equal to the defined
// limit in bytes:
limitMultiFileUploadSize: undefined,
// Multipart file uploads add a number of bytes to each uploaded file,
// therefore the following option adds an overhead for each file used
// in the limitMultiFileUploadSize configuration:
limitMultiFileUploadSizeOverhead: 512,
// Set the following option to true to issue all file upload requests
// in a sequential order:
sequentialUploads: false,
// To limit the number of concurrent uploads,
// set the following option to an integer greater than 0:
limitConcurrentUploads: undefined,
// Set the following option to true to force iframe transport uploads:
forceIframeTransport: false,
// Set the following option to the location of a redirect url on the
// origin server, for cross-domain iframe transport uploads:
redirect: undefined,
// The parameter name for the redirect url, sent as part of the form
// data and set to 'redirect' if this option is empty:
redirectParamName: undefined,
// Set the following option to the location of a postMessage window,
// to enable postMessage transport uploads:
postMessage: undefined,
// By default, XHR file uploads are sent as multipart/form-data.
// The iframe transport is always using multipart/form-data.
// Set to false to enable non-multipart XHR uploads:
multipart: true,
// To upload large files in smaller chunks, set the following option
// to a preferred maximum chunk size. If set to 0, null or undefined,
// or the browser does not support the required Blob API, files will
// be uploaded as a whole.
maxChunkSize: undefined,
// When a non-multipart upload or a chunked multipart upload has been
// aborted, this option can be used to resume the upload by setting
// it to the size of the already uploaded bytes. This option is most
// useful when modifying the options object inside of the "add" or
// "send" callbacks, as the options are cloned for each file upload.
uploadedBytes: undefined,
// By default, failed (abort or error) file uploads are removed from the
// global progress calculation. Set the following option to false to
// prevent recalculating the global progress data:
recalculateProgress: true,
// Interval in milliseconds to calculate and trigger progress events:
progressInterval: 100,
// Interval in milliseconds to calculate progress bitrate:
bitrateInterval: 500,
// By default, uploads are started automatically when adding files:
autoUpload: true,
// Error and info messages:
messages: {
uploadedBytes: 'Uploaded bytes exceed file size'
},
// Translation function, gets the message key to be translated
// and an object with context specific data as arguments:
i18n: function (message, context) {
message = this.messages[message] || message.toString();
if (context) {
$.each(context, function (key, value) {
message = message.replace('{' + key + '}', value);
});
}
return message;
},
// Additional form data to be sent along with the file uploads can be set
// using this option, which accepts an array of objects with name and
// value properties, a function returning such an array, a FormData
// object (for XHR file uploads), or a simple object.
// The form of the first fileInput is given as parameter to the function:
formData: function (form) {
return form.serializeArray();
},
// The add callback is invoked as soon as files are added to the fileupload
// widget (via file input selection, drag & drop, paste or add API call).
// If the singleFileUploads option is enabled, this callback will be
// called once for each file in the selection for XHR file uploads, else
// once for each file selection.
//
// The upload starts when the submit method is invoked on the data parameter.
// The data object contains a files property holding the added files
// and allows you to override plugin options as well as define ajax settings.
//
// Listeners for this callback can also be bound the following way:
// .bind('fileuploadadd', func);
//
// data.submit() returns a Promise object and allows to attach additional
// handlers using jQuery's Deferred callbacks:
// data.submit().done(func).fail(func).always(func);
add: function (e, data) {
if (e.isDefaultPrevented()) {
return false;
}
if (data.autoUpload || (data.autoUpload !== false &&
$(this).fileupload('option', 'autoUpload'))) {
data.process().done(function () {
data.submit();
});
}
},
// Other callbacks:
// Callback for the submit event of each file upload:
// submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
// Callback for the start of each file upload request:
// send: function (e, data) {}, // .bind('fileuploadsend', func);
// Callback for successful uploads:
// done: function (e, data) {}, // .bind('fileuploaddone', func);
// Callback for failed (abort or error) uploads:
// fail: function (e, data) {}, // .bind('fileuploadfail', func);
// Callback for completed (success, abort or error) requests:
// always: function (e, data) {}, // .bind('fileuploadalways', func);
// Callback for upload progress events:
// progress: function (e, data) {}, // .bind('fileuploadprogress', func);
// Callback for global upload progress events:
// progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
// Callback for uploads start, equivalent to the global ajaxStart event:
// start: function (e) {}, // .bind('fileuploadstart', func);
// Callback for uploads stop, equivalent to the global ajaxStop event:
// stop: function (e) {}, // .bind('fileuploadstop', func);
// Callback for change events of the fileInput(s):
// change: function (e, data) {}, // .bind('fileuploadchange', func);
// Callback for paste events to the pasteZone(s):
// paste: function (e, data) {}, // .bind('fileuploadpaste', func);
// Callback for drop events of the dropZone(s):
// drop: function (e, data) {}, // .bind('fileuploaddrop', func);
// Callback for dragover events of the dropZone(s):
// dragover: function (e) {}, // .bind('fileuploaddragover', func);
// Callback for the start of each chunk upload request:
// chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);
// Callback for successful chunk uploads:
// chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);
// Callback for failed (abort or error) chunk uploads:
// chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);
// Callback for completed (success, abort or error) chunk upload requests:
// chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);
// The plugin options are used as settings object for the ajax calls.
// The following are jQuery ajax settings required for the file uploads:
processData: false,
contentType: false,
cache: false,
timeout: 0
},
// A list of options that require reinitializing event listeners and/or
// special initialization code:
_specialOptions: [
'fileInput',
'dropZone',
'pasteZone',
'multipart',
'forceIframeTransport'
],
_blobSlice: $.support.blobSlice && function () {
var slice = this.slice || this.webkitSlice || this.mozSlice;
return slice.apply(this, arguments);
},
_BitrateTimer: function () {
this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
this.loaded = 0;
this.bitrate = 0;
this.getBitrate = function (now, loaded, interval) {
var timeDiff = now - this.timestamp;
if (!this.bitrate || !interval || timeDiff > interval) {
this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
this.loaded = loaded;
this.timestamp = now;
}
return this.bitrate;
};
},
_isXHRUpload: function (options) {
return !options.forceIframeTransport &&
((!options.multipart && $.support.xhrFileUpload) ||
$.support.xhrFormDataFileUpload);
},
_getFormData: function (options) {
var formData;
if ($.type(options.formData) === 'function') {
return options.formData(options.form);
}
if ($.isArray(options.formData)) {
return options.formData;
}
if ($.type(options.formData) === 'object') {
formData = [];
$.each(options.formData, function (name, value) {
formData.push({name: name, value: value});
});
return formData;
}
return [];
},
_getTotal: function (files) {
var total = 0;
$.each(files, function (index, file) {
total += file.size || 1;
});
return total;
},
_initProgressObject: function (obj) {
var progress = {
loaded: 0,
total: 0,
bitrate: 0
};
if (obj._progress) {
$.extend(obj._progress, progress);
} else {
obj._progress = progress;
}
},
_initResponseObject: function (obj) {
var prop;
if (obj._response) {
for (prop in obj._response) {
if (obj._response.hasOwnProperty(prop)) {
delete obj._response[prop];
}
}
} else {
obj._response = {};
}
},
_onProgress: function (e, data) {
if (e.lengthComputable) {
var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
loaded;
if (data._time && data.progressInterval &&
(now - data._time < data.progressInterval) &&
e.loaded !== e.total) {
return;
}
data._time = now;
loaded = Math.floor(
e.loaded / e.total * (data.chunkSize || data._progress.total)
) + (data.uploadedBytes || 0);
// Add the difference from the previously loaded state
// to the global loaded counter:
this._progress.loaded += (loaded - data._progress.loaded);
this._progress.bitrate = this._bitrateTimer.getBitrate(
now,
this._progress.loaded,
data.bitrateInterval
);
data._progress.loaded = data.loaded = loaded;
data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
now,
loaded,
data.bitrateInterval
);
// Trigger a custom progress event with a total data property set
// to the file size(s) of the current upload and a loaded data
// property calculated accordingly:
this._trigger(
'progress',
$.Event('progress', {delegatedEvent: e}),
data
);
// Trigger a global progress event for all current file uploads,
// including ajax calls queued for sequential file uploads:
this._trigger(
'progressall',
$.Event('progressall', {delegatedEvent: e}),
this._progress
);
}
},
_initProgressListener: function (options) {
var that = this,
xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
// Accesss to the native XHR object is required to add event listeners
// for the upload progress event:
if (xhr.upload) {
$(xhr.upload).bind('progress', function (e) {
var oe = e.originalEvent;
// Make sure the progress event properties get copied over:
e.lengthComputable = oe.lengthComputable;
e.loaded = oe.loaded;
e.total = oe.total;
that._onProgress(e, options);
});
options.xhr = function () {
return xhr;
};
}
},
_isInstanceOf: function (type, obj) {
// Cross-frame instanceof check
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
},
_initXHRData: function (options) {
var that = this,
formData,
file = options.files[0],
// Ignore non-multipart setting if not supported:
multipart = options.multipart || !$.support.xhrFileUpload,
paramName = $.type(options.paramName) === 'array' ?
options.paramName[0] : options.paramName;
options.headers = $.extend({}, options.headers);
if (options.contentRange) {
options.headers['Content-Range'] = options.contentRange;
}
if (!multipart || options.blob || !this._isInstanceOf('File', file)) {
options.headers['Content-Disposition'] = 'attachment; filename="' +
encodeURI(file.name) + '"';
}
if (!multipart) {
options.contentType = file.type || 'application/octet-stream';
options.data = options.blob || file;
} else if ($.support.xhrFormDataFileUpload) {
if (options.postMessage) {
// window.postMessage does not allow sending FormData
// objects, so we just add the File/Blob objects to
// the formData array and let the postMessage window
// create the FormData object out of this array:
formData = this._getFormData(options);
if (options.blob) {
formData.push({
name: paramName,
value: options.blob
});
} else {
$.each(options.files, function (index, file) {
formData.push({
name: ($.type(options.paramName) === 'array' &&
options.paramName[index]) || paramName,
value: file
});
});
}
} else {
if (that._isInstanceOf('FormData', options.formData)) {
formData = options.formData;
} else {
formData = new FormData();
$.each(this._getFormData(options), function (index, field) {
formData.append(field.name, field.value);
});
}
if (options.blob) {
formData.append(paramName, options.blob, file.name);
} else {
$.each(options.files, function (index, file) {
// This check allows the tests to run with
// dummy objects:
if (that._isInstanceOf('File', file) ||
that._isInstanceOf('Blob', file)) {
formData.append(
($.type(options.paramName) === 'array' &&
options.paramName[index]) || paramName,
file,
file.uploadName || file.name
);
}
});
}
}
options.data = formData;
}
// Blob reference is not needed anymore, free memory:
options.blob = null;
},
_initIframeSettings: function (options) {
var targetHost = $('<a></a>').prop('href', options.url).prop('host');
// Setting the dataType to iframe enables the iframe transport:
options.dataType = 'iframe ' + (options.dataType || '');
// The iframe transport accepts a serialized array as form data:
options.formData = this._getFormData(options);
// Add redirect url to form data on cross-domain uploads:
if (options.redirect && targetHost && targetHost !== location.host) {
options.formData.push({
name: options.redirectParamName || 'redirect',
value: options.redirect
});
}
},
_initDataSettings: function (options) {
if (this._isXHRUpload(options)) {
if (!this._chunkedUpload(options, true)) {
if (!options.data) {
this._initXHRData(options);
}
this._initProgressListener(options);
}
if (options.postMessage) {
// Setting the dataType to postmessage enables the
// postMessage transport:
options.dataType = 'postmessage ' + (options.dataType || '');
}
} else {
this._initIframeSettings(options);
}
},
_getParamName: function (options) {
var fileInput = $(options.fileInput),
paramName = options.paramName;
if (!paramName) {
paramName = [];
fileInput.each(function () {
var input = $(this),
name = input.prop('name') || 'files[]',
i = (input.prop('files') || [1]).length;
while (i) {
paramName.push(name);
i -= 1;
}
});
if (!paramName.length) {
paramName = [fileInput.prop('name') || 'files[]'];
}
} else if (!$.isArray(paramName)) {
paramName = [paramName];
}
return paramName;
},
_initFormSettings: function (options) {
// Retrieve missing options from the input field and the
// associated form, if available:
if (!options.form || !options.form.length) {
options.form = $(options.fileInput.prop('form'));
// If the given file input doesn't have an associated form,
// use the default widget file input's form:
if (!options.form.length) {
options.form = $(this.options.fileInput.prop('form'));
}
}
options.paramName = this._getParamName(options);
if (!options.url) {
options.url = options.form.prop('action') || location.href;
}
// The HTTP request method must be "POST" or "PUT":
options.type = (options.type ||
($.type(options.form.prop('method')) === 'string' &&
options.form.prop('method')) || ''
).toUpperCase();
if (options.type !== 'POST' && options.type !== 'PUT' &&
options.type !== 'PATCH') {
options.type = 'POST';
}
if (!options.formAcceptCharset) {
options.formAcceptCharset = options.form.attr('accept-charset');
}
},
_getAJAXSettings: function (data) {
var options = $.extend({}, this.options, data);
this._initFormSettings(options);
this._initDataSettings(options);
return options;
},
// jQuery 1.6 doesn't provide .state(),
// while jQuery 1.8+ removed .isRejected() and .isResolved():
_getDeferredState: function (deferred) {
if (deferred.state) {
return deferred.state();
}
if (deferred.isResolved()) {
return 'resolved';
}
if (deferred.isRejected()) {
return 'rejected';
}
return 'pending';
},
// Maps jqXHR callbacks to the equivalent
// methods of the given Promise object:
_enhancePromise: function (promise) {
promise.success = promise.done;
promise.error = promise.fail;
promise.complete = promise.always;
return promise;
},
// Creates and returns a Promise object enhanced with
// the jqXHR methods abort, success, error and complete:
_getXHRPromise: function (resolveOrReject, context, args) {
var dfd = $.Deferred(),
promise = dfd.promise();
context = context || this.options.context || promise;
if (resolveOrReject === true) {
dfd.resolveWith(context, args);
} else if (resolveOrReject === false) {
dfd.rejectWith(context, args);
}
promise.abort = dfd.promise;
return this._enhancePromise(promise);
},
// Adds convenience methods to the data callback argument:
_addConvenienceMethods: function (e, data) {
var that = this,
getPromise = function (args) {
return $.Deferred().resolveWith(that, args).promise();
};
data.process = function (resolveFunc, rejectFunc) {
if (resolveFunc || rejectFunc) {
data._processQueue = this._processQueue =
(this._processQueue || getPromise([this])).then(
function () {
if (data.errorThrown) {
return $.Deferred()
.rejectWith(that, [data]).promise();
}
return getPromise(arguments);
}
).then(resolveFunc, rejectFunc);
}
return this._processQueue || getPromise([this]);
};
data.submit = function () {
if (this.state() !== 'pending') {
data.jqXHR = this.jqXHR =
(that._trigger(
'submit',
$.Event('submit', {delegatedEvent: e}),
this
) !== false) && that._onSend(e, this);
}
return this.jqXHR || that._getXHRPromise();
};
data.abort = function () {
if (this.jqXHR) {
return this.jqXHR.abort();
}
this.errorThrown = 'abort';
that._trigger('fail', null, this);
return that._getXHRPromise(false);
};
data.state = function () {
if (this.jqXHR) {
return that._getDeferredState(this.jqXHR);
}
if (this._processQueue) {
return that._getDeferredState(this._processQueue);
}
};
data.processing = function () {
return !this.jqXHR && this._processQueue && that
._getDeferredState(this._processQueue) === 'pending';
};
data.progress = function () {
return this._progress;
};
data.response = function () {
return this._response;
};
},
// Parses the Range header from the server response
// and returns the uploaded bytes:
_getUploadedBytes: function (jqXHR) {
var range = jqXHR.getResponseHeader('Range'),
parts = range && range.split('-'),
upperBytesPos = parts && parts.length > 1 &&
parseInt(parts[1], 10);
return upperBytesPos && upperBytesPos + 1;
},
// Uploads a file in multiple, sequential requests
// by splitting the file up in multiple blob chunks.
// If the second parameter is true, only tests if the file
// should be uploaded in chunks, but does not invoke any
// upload requests:
_chunkedUpload: function (options, testOnly) {
options.uploadedBytes = options.uploadedBytes || 0;
var that = this,
file = options.files[0],
fs = file.size,
ub = options.uploadedBytes,
mcs = options.maxChunkSize || fs,
slice = this._blobSlice,
dfd = $.Deferred(),
promise = dfd.promise(),
jqXHR,
upload;
if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
options.data) {
return false;
}
if (testOnly) {
return true;
}
if (ub >= fs) {
file.error = options.i18n('uploadedBytes');
return this._getXHRPromise(
false,
options.context,
[null, 'error', file.error]
);
}
// The chunk upload method:
upload = function () {
// Clone the options object for each chunk upload:
var o = $.extend({}, options),
currentLoaded = o._progress.loaded;
o.blob = slice.call(
file,
ub,
ub + mcs,
file.type
);
// Store the current chunk size, as the blob itself
// will be dereferenced after data processing:
o.chunkSize = o.blob.size;
// Expose the chunk bytes position range:
o.contentRange = 'bytes ' + ub + '-' +
(ub + o.chunkSize - 1) + '/' + fs;
// Process the upload data (the blob and potential form data):
that._initXHRData(o);
// Add progress listeners for this chunk upload:
that._initProgressListener(o);
jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||
that._getXHRPromise(false, o.context))
.done(function (result, textStatus, jqXHR) {
ub = that._getUploadedBytes(jqXHR) ||
(ub + o.chunkSize);
// Create a progress event if no final progress event
// with loaded equaling total has been triggered
// for this chunk:
if (currentLoaded + o.chunkSize - o._progress.loaded) {
that._onProgress($.Event('progress', {
lengthComputable: true,
loaded: ub - o.uploadedBytes,
total: ub - o.uploadedBytes
}), o);
}
options.uploadedBytes = o.uploadedBytes = ub;
o.result = result;
o.textStatus = textStatus;
o.jqXHR = jqXHR;
that._trigger('chunkdone', null, o);
that._trigger('chunkalways', null, o);
if (ub < fs) {
// File upload not yet complete,
// continue with the next chunk:
upload();
} else {
dfd.resolveWith(
o.context,
[result, textStatus, jqXHR]
);
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
o.jqXHR = jqXHR;
o.textStatus = textStatus;
o.errorThrown = errorThrown;
that._trigger('chunkfail', null, o);
that._trigger('chunkalways', null, o);
dfd.rejectWith(
o.context,
[jqXHR, textStatus, errorThrown]
);
});
};
this._enhancePromise(promise);
promise.abort = function () {
return jqXHR.abort();
};
upload();
return promise;
},
_beforeSend: function (e, data) {
if (this._active === 0) {
// the start callback is triggered when an upload starts
// and no other uploads are currently running,
// equivalent to the global ajaxStart event:
this._trigger('start');
// Set timer for global bitrate progress calculation:
this._bitrateTimer = new this._BitrateTimer();
// Reset the global progress values:
this._progress.loaded = this._progress.total = 0;
this._progress.bitrate = 0;
}
// Make sure the container objects for the .response() and
// .progress() methods on the data object are available
// and reset to their initial state:
this._initResponseObject(data);
this._initProgressObject(data);
data._progress.loaded = data.loaded = data.uploadedBytes || 0;
data._progress.total = data.total = this._getTotal(data.files) || 1;
data._progress.bitrate = data.bitrate = 0;
this._active += 1;
// Initialize the global progress values:
this._progress.loaded += data.loaded;
this._progress.total += data.total;
},
_onDone: function (result, textStatus, jqXHR, options) {
var total = options._progress.total,
response = options._response;
if (options._progress.loaded < total) {
// Create a progress event if no final progress event
// with loaded equaling total has been triggered:
this._onProgress($.Event('progress', {
lengthComputable: true,
loaded: total,
total: total
}), options);
}
response.result = options.result = result;
response.textStatus = options.textStatus = textStatus;
response.jqXHR = options.jqXHR = jqXHR;
this._trigger('done', null, options);
},
_onFail: function (jqXHR, textStatus, errorThrown, options) {
var response = options._response;
if (options.recalculateProgress) {
// Remove the failed (error or abort) file upload from
// the global progress calculation:
this._progress.loaded -= options._progress.loaded;
this._progress.total -= options._progress.total;
}
response.jqXHR = options.jqXHR = jqXHR;
response.textStatus = options.textStatus = textStatus;
response.errorThrown = options.errorThrown = errorThrown;
this._trigger('fail', null, options);
},
_onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
// jqXHRorResult, textStatus and jqXHRorError are added to the
// options object via done and fail callbacks
this._trigger('always', null, options);
},
_onSend: function (e, data) {
if (!data.submit) {
this._addConvenienceMethods(e, data);
}
var that = this,
jqXHR,
aborted,
slot,
pipe,
options = that._getAJAXSettings(data),
send = function () {
that._sending += 1;
// Set timer for bitrate progress calculation:
options._bitrateTimer = new that._BitrateTimer();
jqXHR = jqXHR || (
((aborted || that._trigger(
'send',
$.Event('send', {delegatedEvent: e}),
options
) === false) &&
that._getXHRPromise(false, options.context, aborted)) ||
that._chunkedUpload(options) || $.ajax(options)
).done(function (result, textStatus, jqXHR) {
that._onDone(result, textStatus, jqXHR, options);
}).fail(function (jqXHR, textStatus, errorThrown) {
that._onFail(jqXHR, textStatus, errorThrown, options);
}).always(function (jqXHRorResult, textStatus, jqXHRorError) {
that._onAlways(
jqXHRorResult,
textStatus,
jqXHRorError,
options
);
that._sending -= 1;
that._active -= 1;
if (options.limitConcurrentUploads &&
options.limitConcurrentUploads > that._sending) {
// Start the next queued upload,
// that has not been aborted:
var nextSlot = that._slots.shift();
while (nextSlot) {
if (that._getDeferredState(nextSlot) === 'pending') {
nextSlot.resolve();
break;
}
nextSlot = that._slots.shift();
}
}
if (that._active === 0) {
// The stop callback is triggered when all uploads have
// been completed, equivalent to the global ajaxStop event:
that._trigger('stop');
}
});
return jqXHR;
};
this._beforeSend(e, options);
if (this.options.sequentialUploads ||
(this.options.limitConcurrentUploads &&
this.options.limitConcurrentUploads <= this._sending)) {
if (this.options.limitConcurrentUploads > 1) {
slot = $.Deferred();
this._slots.push(slot);
pipe = slot.then(send);
} else {
this._sequence = this._sequence.then(send, send);
pipe = this._sequence;
}
// Return the piped Promise object, enhanced with an abort method,
// which is delegated to the jqXHR object of the current upload,
// and jqXHR callbacks mapped to the equivalent Promise methods:
pipe.abort = function () {
aborted = [undefined, 'abort', 'abort'];
if (!jqXHR) {
if (slot) {
slot.rejectWith(options.context, aborted);
}
return send();
}
return jqXHR.abort();
};
return this._enhancePromise(pipe);
}
return send();
},
_onAdd: function (e, data) {
var that = this,
result = true,
options = $.extend({}, this.options, data),
files = data.files,
filesLength = files.length,
limit = options.limitMultiFileUploads,
limitSize = options.limitMultiFileUploadSize,
overhead = options.limitMultiFileUploadSizeOverhead,
batchSize = 0,
paramName = this._getParamName(options),
paramNameSet,
paramNameSlice,
fileSet,
i,
j = 0;
if (!filesLength) {
return false;
}
if (limitSize && files[0].size === undefined) {
limitSize = undefined;
}
if (!(options.singleFileUploads || limit || limitSize) ||
!this._isXHRUpload(options)) {
fileSet = [files];
paramNameSet = [paramName];
} else if (!(options.singleFileUploads || limitSize) && limit) {
fileSet = [];
paramNameSet = [];
for (i = 0; i < filesLength; i += limit) {
fileSet.push(files.slice(i, i + limit));
paramNameSlice = paramName.slice(i, i + limit);
if (!paramNameSlice.length) {
paramNameSlice = paramName;
}
paramNameSet.push(paramNameSlice);
}
} else if (!options.singleFileUploads && limitSize) {
fileSet = [];
paramNameSet = [];
for (i = 0; i < filesLength; i = i + 1) {
batchSize += files[i].size + overhead;
if (i + 1 === filesLength ||
((batchSize + files[i + 1].size + overhead) > limitSize) ||
(limit && i + 1 - j >= limit)) {
fileSet.push(files.slice(j, i + 1));
paramNameSlice = paramName.slice(j, i + 1);
if (!paramNameSlice.length) {
paramNameSlice = paramName;
}
paramNameSet.push(paramNameSlice);
j = i + 1;
batchSize = 0;
}
}
} else {
paramNameSet = paramName;
}
data.originalFiles = files;
$.each(fileSet || files, function (index, element) {
var newData = $.extend({}, data);
newData.files = fileSet ? element : [element];
newData.paramName = paramNameSet[index];
that._initResponseObject(newData);
that._initProgressObject(newData);
that._addConvenienceMethods(e, newData);
result = that._trigger(
'add',
$.Event('add', {delegatedEvent: e}),
newData
);
return result;
});
return result;
},
_replaceFileInput: function (data) {
var input = data.fileInput,
inputClone = input.clone(true),
restoreFocus = input.is(document.activeElement);
// Add a reference for the new cloned file input to the data argument:
data.fileInputClone = inputClone;
$('<form></form>').append(inputClone)[0].reset();
// Detaching allows to insert the fileInput on another form
// without loosing the file input value:
input.after(inputClone).detach();
// If the fileInput had focus before it was detached,
// restore focus to the inputClone.
if (restoreFocus) {
inputClone.focus();
}
// Avoid memory leaks with the detached file input:
$.cleanData(input.unbind('remove'));
// Replace the original file input element in the fileInput
// elements set with the clone, which has been copied including
// event handlers:
this.options.fileInput = this.options.fileInput.map(function (i, el) {
if (el === input[0]) {
return inputClone[0];
}
return el;
});
// If the widget has been initialized on the file input itself,
// override this.element with the file input clone:
if (input[0] === this.element[0]) {
this.element = inputClone;
}
},
_handleFileTreeEntry: function (entry, path) {
var that = this,
dfd = $.Deferred(),
errorHandler = function (e) {
if (e && !e.entry) {
e.entry = entry;
}
// Since $.when returns immediately if one
// Deferred is rejected, we use resolve instead.
// This allows valid files and invalid items
// to be returned together in one set:
dfd.resolve([e]);
},
successHandler = function (entries) {
that._handleFileTreeEntries(
entries,
path + entry.name + '/'
).done(function (files) {
dfd.resolve(files);
}).fail(errorHandler);
},
readEntries = function () {
dirReader.readEntries(function (results) {
if (!results.length) {
successHandler(entries);
} else {
entries = entries.concat(results);
readEntries();
}
}, errorHandler);
},
dirReader, entries = [];
path = path || '';
if (entry.isFile) {
if (entry._file) {
// Workaround for Chrome bug #149735
entry._file.relativePath = path;
dfd.resolve(entry._file);
} else {
entry.file(function (file) {
file.relativePath = path;
dfd.resolve(file);
}, errorHandler);
}
} else if (entry.isDirectory) {
dirReader = entry.createReader();
readEntries();
} else {
// Return an empy list for file system items
// other than files or directories:
dfd.resolve([]);
}
return dfd.promise();
},
_handleFileTreeEntries: function (entries, path) {
var that = this;
return $.when.apply(
$,
$.map(entries, function (entry) {
return that._handleFileTreeEntry(entry, path);
})
).then(function () {
return Array.prototype.concat.apply(
[],
arguments
);
});
},
_getDroppedFiles: function (dataTransfer) {
dataTransfer = dataTransfer || {};
var items = dataTransfer.items;
if (items && items.length && (items[0].webkitGetAsEntry ||
items[0].getAsEntry)) {
return this._handleFileTreeEntries(
$.map(items, function (item) {
var entry;
if (item.webkitGetAsEntry) {
entry = item.webkitGetAsEntry();
if (entry) {
// Workaround for Chrome bug #149735:
entry._file = item.getAsFile();
}
return entry;
}
return item.getAsEntry();
})
);
}
return $.Deferred().resolve(
$.makeArray(dataTransfer.files)
).promise();
},
_getSingleFileInputFiles: function (fileInput) {
fileInput = $(fileInput);
var entries = fileInput.prop('webkitEntries') ||
fileInput.prop('entries'),
files,
value;
if (entries && entries.length) {
return this._handleFileTreeEntries(entries);
}
files = $.makeArray(fileInput.prop('files'));
if (!files.length) {
value = fileInput.prop('value');
if (!value) {
return $.Deferred().resolve([]).promise();
}
// If the files property is not available, the browser does not
// support the File API and we add a pseudo File object with
// the input value as name with path information removed:
files = [{name: value.replace(/^.*\\/, '')}];
} else if (files[0].name === undefined && files[0].fileName) {
// File normalization for Safari 4 and Firefox 3:
$.each(files, function (index, file) {
file.name = file.fileName;
file.size = file.fileSize;
});
}
return $.Deferred().resolve(files).promise();
},
_getFileInputFiles: function (fileInput) {
if (!(fileInput instanceof $) || fileInput.length === 1) {
return this._getSingleFileInputFiles(fileInput);
}
return $.when.apply(
$,
$.map(fileInput, this._getSingleFileInputFiles)
).then(function () {
return Array.prototype.concat.apply(
[],
arguments
);
});
},
_onChange: function (e) {
var that = this,
data = {
fileInput: $(e.target),
form: $(e.target.form)
};
this._getFileInputFiles(data.fileInput).always(function (files) {
data.files = files;
if (that.options.replaceFileInput) {
that._replaceFileInput(data);
}
if (that._trigger(
'change',
$.Event('change', {delegatedEvent: e}),
data
) !== false) {
that._onAdd(e, data);
}
});
},
_onPaste: function (e) {
var items = e.originalEvent && e.originalEvent.clipboardData &&
e.originalEvent.clipboardData.items,
data = {files: []};
if (items && items.length) {
$.each(items, function (index, item) {
var file = item.getAsFile && item.getAsFile();
if (file) {
data.files.push(file);
}
});
if (this._trigger(
'paste',
$.Event('paste', {delegatedEvent: e}),
data
) !== false) {
this._onAdd(e, data);
}
}
},
_onDrop: function (e) {
e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
var that = this,
dataTransfer = e.dataTransfer,
data = {};
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
e.preventDefault();
this._getDroppedFiles(dataTransfer).always(function (files) {
data.files = files;
if (that._trigger(
'drop',
$.Event('drop', {delegatedEvent: e}),
data
) !== false) {
that._onAdd(e, data);
}
});
}
},
_onDragOver: getDragHandler('dragover'),
_onDragEnter: getDragHandler('dragenter'),
_onDragLeave: getDragHandler('dragleave'),
_initEventHandlers: function () {
if (this._isXHRUpload(this.options)) {
this._on(this.options.dropZone, {
dragover: this._onDragOver,
drop: this._onDrop,
// event.preventDefault() on dragenter is required for IE10+:
dragenter: this._onDragEnter,
// dragleave is not required, but added for completeness:
dragleave: this._onDragLeave
});
this._on(this.options.pasteZone, {
paste: this._onPaste
});
}
if ($.support.fileInput) {
this._on(this.options.fileInput, {
change: this._onChange
});
}
},
_destroyEventHandlers: function () {
this._off(this.options.dropZone, 'dragenter dragleave dragover drop');
this._off(this.options.pasteZone, 'paste');
this._off(this.options.fileInput, 'change');
},
_setOption: function (key, value) {
var reinit = $.inArray(key, this._specialOptions) !== -1;
if (reinit) {
this._destroyEventHandlers();
}
this._super(key, value);
if (reinit) {
this._initSpecialOptions();
this._initEventHandlers();
}
},
_initSpecialOptions: function () {
var options = this.options;
if (options.fileInput === undefined) {
options.fileInput = this.element.is('input[type="file"]') ?
this.element : this.element.find('input[type="file"]');
} else if (!(options.fileInput instanceof $)) {
options.fileInput = $(options.fileInput);
}
if (!(options.dropZone instanceof $)) {
options.dropZone = $(options.dropZone);
}
if (!(options.pasteZone instanceof $)) {
options.pasteZone = $(options.pasteZone);
}
},
_getRegExp: function (str) {
var parts = str.split('/'),
modifiers = parts.pop();
parts.shift();
return new RegExp(parts.join('/'), modifiers);
},
_isRegExpOption: function (key, value) {
return key !== 'url' && $.type(value) === 'string' &&
/^\/.*\/[igm]{0,3}$/.test(value);
},
_initDataAttributes: function () {
var that = this,
options = this.options,
data = this.element.data();
// Initialize options set via HTML5 data-attributes:
$.each(
this.element[0].attributes,
function (index, attr) {
var key = attr.name.toLowerCase(),
value;
if (/^data-/.test(key)) {
// Convert hyphen-ated key to camelCase:
key = key.slice(5).replace(/-[a-z]/g, function (str) {
return str.charAt(1).toUpperCase();
});
value = data[key];
if (that._isRegExpOption(key, value)) {
value = that._getRegExp(value);
}
options[key] = value;
}
}
);
},
_create: function () {
this._initDataAttributes();
this._initSpecialOptions();
this._slots = [];
this._sequence = this._getXHRPromise(true);
this._sending = this._active = 0;
this._initProgressObject(this);
this._initEventHandlers();
},
// This method is exposed to the widget API and allows to query
// the number of active uploads:
active: function () {
return this._active;
},
// This method is exposed to the widget API and allows to query
// the widget upload progress.
// It returns an object with loaded, total and bitrate properties
// for the running uploads:
progress: function () {
return this._progress;
},
// This method is exposed to the widget API and allows adding files
// using the fileupload API. The data parameter accepts an object which
// must have a files property and can contain additional options:
// .fileupload('add', {files: filesList});
add: function (data) {
var that = this;
if (!data || this.options.disabled) {
return;
}
if (data.fileInput && !data.files) {
this._getFileInputFiles(data.fileInput).always(function (files) {
data.files = files;
that._onAdd(null, data);
});
} else {
data.files = $.makeArray(data.files);
this._onAdd(null, data);
}
},
// This method is exposed to the widget API and allows sending files
// using the fileupload API. The data parameter accepts an object which
// must have a files or fileInput property and can contain additional options:
// .fileupload('send', {files: filesList});
// The method returns a Promise object for the file upload call.
send: function (data) {
if (data && !this.options.disabled) {
if (data.fileInput && !data.files) {
var that = this,
dfd = $.Deferred(),
promise = dfd.promise(),
jqXHR,
aborted;
promise.abort = function () {
aborted = true;
if (jqXHR) {
return jqXHR.abort();
}
dfd.reject(null, 'abort', 'abort');
return promise;
};
this._getFileInputFiles(data.fileInput).always(
function (files) {
if (aborted) {
return;
}
if (!files.length) {
dfd.reject();
return;
}
data.files = files;
jqXHR = that._onSend(null, data);
jqXHR.then(
function (result, textStatus, jqXHR) {
dfd.resolve(result, textStatus, jqXHR);
},
function (jqXHR, textStatus, errorThrown) {
dfd.reject(jqXHR, textStatus, errorThrown);
}
);
}
);
return this._enhancePromise(promise);
}
data.files = $.makeArray(data.files);
if (data.files.length) {
return this._onSend(null, data);
}
}
return this._getXHRPromise(false, data && data.context);
}
});
}));
/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28
* http://jqueryui.com
* Includes: widget.js
* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define([ "jquery" ], factory );
} else if ( typeof exports === "object" ) {
// Node/CommonJS
factory( require( "jquery" ) );
} else {
// Browser globals
factory( jQuery );
}
}(function( $ ) {
/*!
* jQuery UI Widget 1.11.4
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/jQuery.widget/
*/
var widget_uuid = 0,
widget_slice = Array.prototype.slice;
$.cleanData = (function( orig ) {
return function( elems ) {
var events, elem, i;
for ( i = 0; (elem = elems[i]) != null; i++ ) {
try {
// Only trigger remove when necessary to save time
events = $._data( elem, "events" );
if ( events && events.remove ) {
$( elem ).triggerHandler( "remove" );
}
// http://bugs.jquery.com/ticket/8235
} catch ( e ) {}
}
orig( elems );
};
})( $.cleanData );
$.widget = function( name, base, prototype ) {
var fullName, existingConstructor, constructor, basePrototype,
// proxiedPrototype allows the provided prototype to remain unmodified
// so that it can be used as a mixin for multiple widgets (#8876)
proxiedPrototype = {},
namespace = name.split( "." )[ 0 ];
name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name;
if ( !prototype ) {
prototype = base;
base = $.Widget;
}
// create selector for plugin
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
return !!$.data( elem, fullName );
};
$[ namespace ] = $[ namespace ] || {};
existingConstructor = $[ namespace ][ name ];
constructor = $[ namespace ][ name ] = function( options, element ) {
// allow instantiation without "new" keyword
if ( !this._createWidget ) {
return new constructor( options, element );
}
// allow instantiation without initializing for simple inheritance
// must use "new" keyword (the code above always passes args)
if ( arguments.length ) {
this._createWidget( options, element );
}
};
// extend with the existing constructor to carry over any static properties
$.extend( constructor, existingConstructor, {
version: prototype.version,
// copy the object used to create the prototype in case we need to
// redefine the widget later
_proto: $.extend( {}, prototype ),
// track widgets that inherit from this widget in case this widget is
// redefined after a widget inherits from it
_childConstructors: []
});
basePrototype = new base();
// we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're
// inheriting from
basePrototype.options = $.widget.extend( {}, basePrototype.options );
$.each( prototype, function( prop, value ) {
if ( !$.isFunction( value ) ) {
proxiedPrototype[ prop ] = value;
return;
}
proxiedPrototype[ prop ] = (function() {
var _super = function() {
return base.prototype[ prop ].apply( this, arguments );
},
_superApply = function( args ) {
return base.prototype[ prop ].apply( this, args );
};
return function() {
var __super = this._super,
__superApply = this._superApply,
returnValue;
this._super = _super;
this._superApply = _superApply;
returnValue = value.apply( this, arguments );
this._super = __super;
this._superApply = __superApply;
return returnValue;
};
})();
});
constructor.prototype = $.widget.extend( basePrototype, {
// TODO: remove support for widgetEventPrefix
// always use the name + a colon as the prefix, e.g., draggable:start
// don't prefix for widgets that aren't DOM-based
widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
}, proxiedPrototype, {
constructor: constructor,
namespace: namespace,
widgetName: name,
widgetFullName: fullName
});
// If this widget is being redefined then we need to find all widgets that
// are inheriting from it and redefine all of them so that they inherit from
// the new version of this widget. We're essentially trying to replace one
// level in the prototype chain.
if ( existingConstructor ) {
$.each( existingConstructor._childConstructors, function( i, child ) {
var childPrototype = child.prototype;
// redefine the child widget using the same prototype that was
// originally used, but inherit from the new version of the base
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
});
// remove the list of existing child constructors from the old constructor
// so the old child constructors can be garbage collected
delete existingConstructor._childConstructors;
} else {
base._childConstructors.push( constructor );
}
$.widget.bridge( name, constructor );
return constructor;
};
$.widget.extend = function( target ) {
var input = widget_slice.call( arguments, 1 ),
inputIndex = 0,
inputLength = input.length,
key,
value;
for ( ; inputIndex < inputLength; inputIndex++ ) {
for ( key in input[ inputIndex ] ) {
value = input[ inputIndex ][ key ];
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
// Clone objects
if ( $.isPlainObject( value ) ) {
target[ key ] = $.isPlainObject( target[ key ] ) ?
$.widget.extend( {}, target[ key ], value ) :
// Don't extend strings, arrays, etc. with objects
$.widget.extend( {}, value );
// Copy everything else by reference
} else {
target[ key ] = value;
}
}
}
}
return target;
};
$.widget.bridge = function( name, object ) {
var fullName = object.prototype.widgetFullName || name;
$.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string",
args = widget_slice.call( arguments, 1 ),
returnValue = this;
if ( isMethodCall ) {
this.each(function() {
var methodValue,
instance = $.data( this, fullName );
if ( options === "instance" ) {
returnValue = instance;
return false;
}
if ( !instance ) {
return $.error( "cannot call methods on " + name + " prior to initialization; " +
"attempted to call method '" + options + "'" );
}
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
}
methodValue = instance[ options ].apply( instance, args );
if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue && methodValue.jquery ?
returnValue.pushStack( methodValue.get() ) :
methodValue;
return false;
}
});
} else {
// Allow multiple hashes to be passed on init
if ( args.length ) {
options = $.widget.extend.apply( null, [ options ].concat(args) );
}
this.each(function() {
var instance = $.data( this, fullName );
if ( instance ) {
instance.option( options || {} );
if ( instance._init ) {
instance._init();
}
} else {
$.data( this, fullName, new object( options, this ) );
}
});
}
return returnValue;
};
};
$.Widget = function( /* options, element */ ) {};
$.Widget._childConstructors = [];
$.Widget.prototype = {
widgetName: "widget",
widgetEventPrefix: "",
defaultElement: "<div>",
options: {
disabled: false,
// callbacks
create: null
},
_createWidget: function( options, element ) {
element = $( element || this.defaultElement || this )[ 0 ];
this.element = $( element );
this.uuid = widget_uuid++;
this.eventNamespace = "." + this.widgetName + this.uuid;
this.bindings = $();
this.hoverable = $();
this.focusable = $();
if ( element !== this ) {
$.data( element, this.widgetFullName, this );
this._on( true, this.element, {
remove: function( event ) {
if ( event.target === element ) {
this.destroy();
}
}
});
this.document = $( element.style ?
// element within the document
element.ownerDocument :
// element is window or document
element.document || element );
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
}
this.options = $.widget.extend( {},
this.options,
this._getCreateOptions(),
options );
this._create();
this._trigger( "create", null, this._getCreateEventData() );
this._init();
},
_getCreateOptions: $.noop,
_getCreateEventData: $.noop,
_create: $.noop,
_init: $.noop,
destroy: function() {
this._destroy();
// we can probably remove the unbind calls in 2.0
// all event bindings should go through this._on()
this.element
.unbind( this.eventNamespace )
.removeData( this.widgetFullName )
// support: jquery <1.6.3
// http://bugs.jquery.com/ticket/9413
.removeData( $.camelCase( this.widgetFullName ) );
this.widget()
.unbind( this.eventNamespace )
.removeAttr( "aria-disabled" )
.removeClass(
this.widgetFullName + "-disabled " +
"ui-state-disabled" );
// clean up events and states
this.bindings.unbind( this.eventNamespace );
this.hoverable.removeClass( "ui-state-hover" );
this.focusable.removeClass( "ui-state-focus" );
},
_destroy: $.noop,
widget: function() {
return this.element;
},
option: function( key, value ) {
var options = key,
parts,
curOption,
i;
if ( arguments.length === 0 ) {
// don't return a reference to the internal hash
return $.widget.extend( {}, this.options );
}
if ( typeof key === "string" ) {
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
options = {};
parts = key.split( "." );
key = parts.shift();
if ( parts.length ) {
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
for ( i = 0; i < parts.length - 1; i++ ) {
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
curOption = curOption[ parts[ i ] ];
}
key = parts.pop();
if ( arguments.length === 1 ) {
return curOption[ key ] === undefined ? null : curOption[ key ];
}
curOption[ key ] = value;
} else {
if ( arguments.length === 1 ) {
return this.options[ key ] === undefined ? null : this.options[ key ];
}
options[ key ] = value;
}
}
this._setOptions( options );
return this;
},
_setOptions: function( options ) {
var key;
for ( key in options ) {
this._setOption( key, options[ key ] );
}
return this;
},
_setOption: function( key, value ) {
this.options[ key ] = value;
if ( key === "disabled" ) {
this.widget()
.toggleClass( this.widgetFullName + "-disabled", !!value );
// If the widget is becoming disabled, then nothing is interactive
if ( value ) {
this.hoverable.removeClass( "ui-state-hover" );
this.focusable.removeClass( "ui-state-focus" );
}
}
return this;
},
enable: function() {
return this._setOptions({ disabled: false });
},
disable: function() {
return this._setOptions({ disabled: true });
},
_on: function( suppressDisabledCheck, element, handlers ) {
var delegateElement,
instance = this;
// no suppressDisabledCheck flag, shuffle arguments
if ( typeof suppressDisabledCheck !== "boolean" ) {
handlers = element;
element = suppressDisabledCheck;
suppressDisabledCheck = false;
}
// no element argument, shuffle and use this.element
if ( !handlers ) {
handlers = element;
element = this.element;
delegateElement = this.widget();
} else {
element = delegateElement = $( element );
this.bindings = this.bindings.add( element );
}
$.each( handlers, function( event, handler ) {
function handlerProxy() {
// allow widgets to customize the disabled handling
// - disabled as an array instead of boolean
// - disabled class as method for disabling individual parts
if ( !suppressDisabledCheck &&
( instance.options.disabled === true ||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
return;
}
return ( typeof handler === "string" ? instance[ handler ] : handler )
.apply( instance, arguments );
}
// copy the guid so direct unbinding works
if ( typeof handler !== "string" ) {
handlerProxy.guid = handler.guid =
handler.guid || handlerProxy.guid || $.guid++;
}
var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
eventName = match[1] + instance.eventNamespace,
selector = match[2];
if ( selector ) {
delegateElement.delegate( selector, eventName, handlerProxy );
} else {
element.bind( eventName, handlerProxy );
}
});
},
_off: function( element, eventName ) {
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
this.eventNamespace;
element.unbind( eventName ).undelegate( eventName );
// Clear the stack to avoid memory leaks (#10056)
this.bindings = $( this.bindings.not( element ).get() );
this.focusable = $( this.focusable.not( element ).get() );
this.hoverable = $( this.hoverable.not( element ).get() );
},
_delay: function( handler, delay ) {
function handlerProxy() {
return ( typeof handler === "string" ? instance[ handler ] : handler )
.apply( instance, arguments );
}
var instance = this;
return setTimeout( handlerProxy, delay || 0 );
},
_hoverable: function( element ) {
this.hoverable = this.hoverable.add( element );
this._on( element, {
mouseenter: function( event ) {
$( event.currentTarget ).addClass( "ui-state-hover" );
},
mouseleave: function( event ) {
$( event.currentTarget ).removeClass( "ui-state-hover" );
}
});
},
_focusable: function( element ) {
this.focusable = this.focusable.add( element );
this._on( element, {
focusin: function( event ) {
$( event.currentTarget ).addClass( "ui-state-focus" );
},
focusout: function( event ) {
$( event.currentTarget ).removeClass( "ui-state-focus" );
}
});
},
_trigger: function( type, event, data ) {
var prop, orig,
callback = this.options[ type ];
data = data || {};
event = $.Event( event );
event.type = ( type === this.widgetEventPrefix ?
type :
this.widgetEventPrefix + type ).toLowerCase();
// the original event may come from any element
// so we need to reset the target on the new event
event.target = this.element[ 0 ];
// copy original event properties over to the new event
orig = event.originalEvent;
if ( orig ) {
for ( prop in orig ) {
if ( !( prop in event ) ) {
event[ prop ] = orig[ prop ];
}
}
}
this.element.trigger( event, data );
return !( $.isFunction( callback ) &&
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
event.isDefaultPrevented() );
}
};
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
if ( typeof options === "string" ) {
options = { effect: options };
}
var hasOptions,
effectName = !options ?
method :
options === true || typeof options === "number" ?
defaultEffect :
options.effect || defaultEffect;
options = options || {};
if ( typeof options === "number" ) {
options = { duration: options };
}
hasOptions = !$.isEmptyObject( options );
options.complete = callback;
if ( options.delay ) {
element.delay( options.delay );
}
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
element[ method ]( options );
} else if ( effectName !== method && element[ effectName ] ) {
element[ effectName ]( options.duration, options.easing, callback );
} else {
element.queue(function( next ) {
$( this )[ method ]();
if ( callback ) {
callback.call( element[ 0 ] );
}
next();
});
}
};
});
var widget = $.widget;
}));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment