Commit 9c5932cd321309552ed7708f928c3b94399aaabe

Authored by 刘基城
2 parents ccb466c6 57c5e2fc

Merge branch 'zhubo' into 'master'

主播



See merge request !1

Too many changes to show.

To preserve performance only 26 of 301 files are displayed.

.classpath
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<classpath>
3   - <classpathentry kind="src" output="target/classes" path="src/main/java">
4   - <attributes>
5   - <attribute name="optional" value="true"/>
6   - <attribute name="maven.pomderived" value="true"/>
7   - </attributes>
8   - </classpathentry>
9   - <classpathentry kind="src" output="target/test-classes" path="src/test/java">
10   - <attributes>
11   - <attribute name="optional" value="true"/>
12   - <attribute name="maven.pomderived" value="true"/>
13   - </attributes>
14   - </classpathentry>
15   - <classpathentry including="**/*.java" kind="src" path="src/main/resources"/>
16   - <classpathentry kind="src" path="src/main/resources/i18n"/>
17   - <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
18   - <attributes>
19   - <attribute name="maven.pomderived" value="true"/>
20   - <attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
21   - </attributes>
22   - </classpathentry>
23   - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
24   - <attributes>
25   - <attribute name="maven.pomderived" value="true"/>
26   - </attributes>
27   - </classpathentry>
28   - <classpathentry kind="output" path="target/classes"/>
29   -</classpath>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<classpath>
  3 + <classpathentry kind="src" output="target/classes" path="src/main/java">
  4 + <attributes>
  5 + <attribute name="optional" value="true"/>
  6 + <attribute name="maven.pomderived" value="true"/>
  7 + </attributes>
  8 + </classpathentry>
  9 + <classpathentry kind="src" output="target/test-classes" path="src/test/java">
  10 + <attributes>
  11 + <attribute name="optional" value="true"/>
  12 + <attribute name="maven.pomderived" value="true"/>
  13 + </attributes>
  14 + </classpathentry>
  15 + <classpathentry including="**/*.java" kind="src" path="src/main/resources"/>
  16 + <classpathentry kind="src" path="src/main/resources/i18n"/>
  17 + <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
  18 + <attributes>
  19 + <attribute name="maven.pomderived" value="true"/>
  20 + <attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
  21 + </attributes>
  22 + </classpathentry>
  23 + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
  24 + <attributes>
  25 + <attribute name="maven.pomderived" value="true"/>
  26 + </attributes>
  27 + </classpathentry>
  28 + <classpathentry kind="output" path="target/classes"/>
  29 +</classpath>
... ...
.gitignore 0 → 100644
  1 +/target/
... ...
.settings/org.eclipse.wst.common.component
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project-modules id="moduleCoreId" project-version="1.5.0">
3   - <wb-module deploy-name="cnlive_live_web">
4   - <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
5   - <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
6   - <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
7   - <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
8   - <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources/i18n"/>
9   - <dependent-module archiveName="cnlive_live_model-0.0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_live_model/cnlive_live_model">
10   - <dependency-type>uses</dependency-type>
11   - </dependent-module>
12   - <dependent-module archiveName="smart-plugin-rest-1.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-plugin-rest/smart-plugin-rest">
13   - <dependency-type>uses</dependency-type>
14   - </dependent-module>
15   - <dependent-module archiveName="cnlive_ks3-1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_ks3/cnlive_ks3">
16   - <dependency-type>uses</dependency-type>
17   - </dependent-module>
18   - <dependent-module archiveName="smart-framework-4.0.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-framework/smart-framework">
19   - <dependency-type>uses</dependency-type>
20   - </dependent-module>
21   - <dependent-module archiveName="smart-plugin-dbcp-1.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-plugin-dbcp/smart-plugin-dbcp">
22   - <dependency-type>uses</dependency-type>
23   - </dependent-module>
24   - <dependent-module archiveName="smart-plugin-i18n-1.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-plugin-i18n/smart-plugin-i18n">
25   - <dependency-type>uses</dependency-type>
26   - </dependent-module>
27   - <dependent-module archiveName="cnlive_mam_commons-0.0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_mam_commons/cnlive_mam_commons">
28   - <dependency-type>uses</dependency-type>
29   - </dependent-module>
30   - <property name="java-output-path" value="/cnlive_live_web/target/classes"/>
31   - <property name="context-root" value="cnlive_live_web"/>
32   - </wb-module>
33   -</project-modules>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project-modules id="moduleCoreId" project-version="1.5.0">
  3 + <wb-module deploy-name="cnlive_live_web">
  4 + <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
  5 + <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
  6 + <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
  7 + <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
  8 + <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources/i18n"/>
  9 + <dependent-module archiveName="cnlive_live_model-0.0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_live_model/cnlive_live_model">
  10 + <dependency-type>uses</dependency-type>
  11 + </dependent-module>
  12 + <dependent-module archiveName="cnlive_ks3-1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_ks3/cnlive_ks3">
  13 + <dependency-type>uses</dependency-type>
  14 + </dependent-module>
  15 + <dependent-module archiveName="smart-framework-4.0.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-framework/smart-framework">
  16 + <dependency-type>uses</dependency-type>
  17 + </dependent-module>
  18 + <dependent-module archiveName="smart-plugin-dbcp-1.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-plugin-dbcp/smart-plugin-dbcp">
  19 + <dependency-type>uses</dependency-type>
  20 + </dependent-module>
  21 + <dependent-module archiveName="smart-plugin-rest-1.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-plugin-rest/smart-plugin-rest">
  22 + <dependency-type>uses</dependency-type>
  23 + </dependent-module>
  24 + <dependent-module archiveName="smart-plugin-i18n-1.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-plugin-i18n/smart-plugin-i18n">
  25 + <dependency-type>uses</dependency-type>
  26 + </dependent-module>
  27 + <dependent-module archiveName="cnlive_mam_commons-0.0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_mam_commons/cnlive_mam_commons">
  28 + <dependency-type>uses</dependency-type>
  29 + </dependent-module>
  30 + <property name="java-output-path" value="/cnlive_live_web/target/classes"/>
  31 + <property name="context-root" value="cnlive_live_web"/>
  32 + </wb-module>
  33 +</project-modules>
... ...
... ... @@ -41,12 +41,6 @@
41 41 <artifactId>javax.servlet-api</artifactId>
42 42 <version>3.0.1</version>
43 43 </dependency>
44   - <dependency>
45   - <groupId>junit</groupId>
46   - <artifactId>junit</artifactId>
47   - <version>3.8.1</version>
48   - <scope>test</scope>
49   - </dependency>
50 44 <!-- jstl -->
51 45 <dependency>
52 46 <groupId>javax.servlet</groupId>
... ... @@ -60,11 +54,6 @@
60 54 <version>0.0.1-SNAPSHOT</version>
61 55 </dependency>
62 56 <dependency>
63   - <groupId>org.smart4j</groupId>
64   - <artifactId>smart-plugin-rest</artifactId>
65   - <version>1.0</version>
66   - </dependency>
67   - <dependency>
68 57 <groupId>com.cnlive</groupId>
69 58 <artifactId>cnlive_media_tools</artifactId>
70 59 <version>1.0.0</version>
... ...
src/main/java/com/cnlive/mz/live/LiveUtils.java deleted 100644 → 0
1   -package com.cnlive.mz.live;
2   -
3   -import java.util.Calendar;
4   -
5   -/**
6   - * 当前项目公共类
7   - *
8   - * @author liujicheng
9   - *
10   - */
11   -public class LiveUtils {
12   - public static String SESSION_KEY_NAME = "userName";
13   - public static String SESSION_KEY_ID = "userId";
14   -
15   - public static String SESSION_ROLE_ID = "roleId";
16   -
17   - public static void main(String[] args) {
18   - String s = new LiveUtils().getRecentMonths();
19   - System.out.println(s);
20   - }
21   -
22   - public static String getRecentMonths() {
23   - int month = Calendar.getInstance().get(Calendar.MONTH);
24   - StringBuffer sb = new StringBuffer();
25   - if (month < 12) {
26   - month = month + 1;
27   - }
28   - for (int i = 1; i <= month; i++) {
29   - String m = "'" + i + "月" + "'";
30   - sb.append(m);
31   - if (i != month) {
32   - sb.append(",");
33   - }
34   - }
35   - return sb.toString();
36   - }
37   -
38   -}
src/main/java/com/cnlive/mz/live/action/ActivityAction.java
... ... @@ -9,7 +9,6 @@
9 9  
10 10 package com.cnlive.mz.live.action;
11 11  
12   -import java.io.IOException;
13 12 import java.util.HashMap;
14 13 import java.util.List;
15 14 import java.util.Map;
... ... @@ -25,16 +24,13 @@ import org.smart4j.framework.mvc.bean.View;
25 24 import org.smart4j.framework.util.CastUtil;
26 25  
27 26 import com.cnlive.mz.commons.Constants;
28   -import com.cnlive.mz.live.LiveUtils;
29   -import com.cnlive.mz.live.bean.Mp4File;
  27 +import com.cnlive.mz.live.common.LiveUtils;
30 28 import com.cnlive.mz.live.entity.TActivity;
31   -import com.cnlive.mz.live.entity.TActivityLog;
32 29 import com.cnlive.mz.live.entity.TChannel;
33 30 import com.cnlive.mz.live.entity.TDefaultVideo;
34 31 import com.cnlive.mz.live.entity.TWowza;
35 32 import com.cnlive.mz.live.entity.VActivityWidthUser;
36 33 import com.cnlive.mz.live.entity.VChannel;
37   -import com.cnlive.mz.live.entity.VWowzaStream;
38 34 import com.cnlive.mz.live.service.TActivityService;
39 35 import com.cnlive.mz.live.service.TChannelService;
40 36 import com.cnlive.mz.live.service.TSignalService;
... ...
src/main/java/com/cnlive/mz/live/action/ChannelAction.java
... ... @@ -20,8 +20,8 @@ import org.smart4j.framework.util.CastUtil;
20 20  
21 21 import com.cnlive.mz.commons.CnliveUtil;
22 22 import com.cnlive.mz.commons.Constants;
23   -import com.cnlive.mz.live.LiveUtils;
24 23 import com.cnlive.mz.live.bean.TWowzaSignalBean;
  24 +import com.cnlive.mz.live.common.LiveUtils;
25 25 import com.cnlive.mz.live.entity.TChannel;
26 26 import com.cnlive.mz.live.entity.TWowza;
27 27 import com.cnlive.mz.live.entity.VChannel;
... ...
src/main/java/com/cnlive/mz/live/action/IndexAction.java
... ... @@ -25,7 +25,7 @@ import org.smart4j.framework.mvc.bean.Result;
25 25 import org.smart4j.framework.mvc.bean.View;
26 26 import org.smart4j.framework.util.CastUtil;
27 27  
28   -import com.cnlive.mz.live.LiveUtils;
  28 +import com.cnlive.mz.live.common.LiveUtils;
29 29 import com.cnlive.mz.live.entity.TActivity;
30 30 import com.cnlive.mz.live.entity.TUser;
31 31 import com.cnlive.mz.live.entity.VChannel;
... ...
src/main/java/com/cnlive/mz/live/action/LiveAction.java 0 → 100644
  1 +/**
  2 + * Project Name:cnlive_live_web
  3 + * File Name:RoomAction.java
  4 + * Package Name:com.cnlive.mz.live.action
  5 + * Date:2016年4月25日下午1:12:48
  6 + * Copyright (c) 2016, cnlive.com All Rights Reserved.
  7 + *
  8 + */
  9 +
  10 +package com.cnlive.mz.live.action;
  11 +
  12 +import java.util.List;
  13 +
  14 +import org.smart4j.framework.dao.bean.Pager;
  15 +import org.smart4j.framework.ioc.annotation.Inject;
  16 +import org.smart4j.framework.mvc.DataContext;
  17 +import org.smart4j.framework.mvc.annotation.Action;
  18 +import org.smart4j.framework.mvc.annotation.Request;
  19 +import org.smart4j.framework.mvc.bean.View;
  20 +import org.smart4j.framework.util.CastUtil;
  21 +
  22 +import com.cnlive.mz.commons.Constants;
  23 +import com.cnlive.mz.live.common.LiveUtils;
  24 +import com.cnlive.mz.live.entity.TLive;
  25 +import com.cnlive.mz.live.entity.TRoom;
  26 +import com.cnlive.mz.live.service.TLiveService;
  27 +import com.cnlive.mz.live.service.TRoomService;
  28 +
  29 +/**
  30 + * TODO: 机构主播和个人主播发起直播活动 <br/>
  31 + * Date: 2016年4月25日 下午1:12:48 <br/>
  32 + *
  33 + * @author liujicheng
  34 + * @version V1.0
  35 + * @since JDK 1.6
  36 + */
  37 +@Action
  38 +public class LiveAction {
  39 + @Inject
  40 + private TLiveService tLiveService;
  41 + @Inject
  42 + private TRoomService tRoomService;
  43 +
  44 + @Request.Get("/live/preload")
  45 + public View preload() {
  46 + int user_id = CastUtil.castInt(DataContext.getRequest().getSession().getAttribute(LiveUtils.SESSION_KEY_ID));
  47 + View view = new View("live/live_add.jsp");
  48 + List<TRoom> tRooms = tRoomService.getTRooms(user_id);
  49 + view.data("tRooms", tRooms);
  50 + return view;
  51 + }
  52 +
  53 + @Request.Get("/live/list/{page_number}")
  54 + public View list(int page_number) {
  55 + int user_id = CastUtil.castInt(DataContext.getRequest().getSession().getAttribute(LiveUtils.SESSION_KEY_ID));
  56 + System.out.println(user_id);
  57 + Pager<TLive> tLive = tLiveService.getTLivePager(page_number, Constants.PAGE_SIZE, user_id);
  58 + return new View("live/live_management.jsp").data("tLive", tLive);
  59 + }
  60 +
  61 +}
... ...
src/main/java/com/cnlive/mz/live/action/RoomAction.java 0 → 100644
  1 +/**
  2 + * Project Name:cnlive_live_web
  3 + * File Name:RoomAction.java
  4 + * Package Name:com.cnlive.mz.live.action
  5 + * Date:2016年4月25日下午1:12:48
  6 + * Copyright (c) 2016, cnlive.com All Rights Reserved.
  7 + *
  8 + */
  9 +
  10 +package com.cnlive.mz.live.action;
  11 +
  12 +import org.smart4j.framework.dao.bean.Pager;
  13 +import org.smart4j.framework.ioc.annotation.Inject;
  14 +import org.smart4j.framework.mvc.DataContext;
  15 +import org.smart4j.framework.mvc.annotation.Action;
  16 +import org.smart4j.framework.mvc.annotation.Request;
  17 +import org.smart4j.framework.mvc.bean.Multiparts;
  18 +import org.smart4j.framework.mvc.bean.Params;
  19 +import org.smart4j.framework.mvc.bean.Result;
  20 +import org.smart4j.framework.mvc.bean.View;
  21 +import org.smart4j.framework.util.CastUtil;
  22 +
  23 +import com.cnlive.mz.commons.Constants;
  24 +import com.cnlive.mz.live.common.LiveUtils;
  25 +import com.cnlive.mz.live.entity.TRoom;
  26 +import com.cnlive.mz.live.service.TRoomService;
  27 +
  28 +/**
  29 + * TODO: 这里用一句话描述当前类的作用 Date: 2016年4月25日 下午1:12:48 <br/>
  30 + *
  31 + * @author liujicheng
  32 + * @version V1.0
  33 + * @since JDK 1.6
  34 + */
  35 +@Action
  36 +public class RoomAction {
  37 + @Inject
  38 + private TRoomService tRoomService;
  39 + int user_id = 0;
  40 +
  41 + @Request.Get("/room/list/{page_number}")
  42 + public View list(int page_number) {
  43 + // int user_id =
  44 + // CastUtil.castInt(DataContext.getRequest().getSession().getAttribute(LiveUtils.SESSION_KEY_ID));
  45 + Pager<TRoom> tRooms = tRoomService.getTRoomPager(page_number, Constants.PAGE_SIZE, user_id);
  46 + return new View("room/room_management.jsp").data("tRooms", tRooms);
  47 + }
  48 +
  49 + @Request.Get("/room/delete/{id}")
  50 + public Result delete(int id) {
  51 + int user_id = CastUtil.castInt(DataContext.getRequest().getSession().getAttribute(LiveUtils.SESSION_KEY_ID));
  52 + boolean success = tRoomService.delete(id, user_id);
  53 + return new Result(success);
  54 + }
  55 +
  56 + // 查看读取
  57 + @Request.Get("/room/edit/{id}")
  58 + public View edit(int id) {
  59 + TRoom tRoom = tRoomService.getTRoomById(id);
  60 + View view = new View("room/room_add.jsp");
  61 + view.data("tRoom", tRoom);
  62 + return view;
  63 + }
  64 +
  65 + @Request.Post("/room/add")
  66 + public Result add(Params params, Multiparts multiparts) {
  67 + int user_id = CastUtil.castInt(DataContext.getRequest().getSession().getAttribute(LiveUtils.SESSION_KEY_ID));
  68 + tRoomService.save(user_id, params, multiparts);
  69 + return new Result(true);
  70 + }
  71 +
  72 + // 查看读取
  73 + @Request.Get("/room/pload")
  74 + public View pload() {
  75 + View view = new View("room/room_add.jsp");
  76 + return view;
  77 + }
  78 +}
... ...
src/main/java/com/cnlive/mz/live/aspect/ActionAspect.java
... ... @@ -4,8 +4,6 @@ import java.lang.reflect.Method;
4 4  
5 5 import javax.servlet.http.HttpServletRequest;
6 6  
7   -import org.slf4j.Logger;
8   -import org.slf4j.LoggerFactory;
9 7 import org.smart4j.framework.aop.AspectProxy;
10 8 import org.smart4j.framework.aop.annotation.Aspect;
11 9 import org.smart4j.framework.mvc.DataContext;
... ...
src/main/java/com/cnlive/mz/live/aspect/AuthFilter.java
... ... @@ -5,7 +5,6 @@ import java.io.IOException;
5 5 import javax.servlet.Filter;
6 6 import javax.servlet.FilterChain;
7 7 import javax.servlet.FilterConfig;
8   -import javax.servlet.ServletContext;
9 8 import javax.servlet.ServletException;
10 9 import javax.servlet.ServletRequest;
11 10 import javax.servlet.ServletResponse;
... ... @@ -15,11 +14,8 @@ import javax.servlet.http.HttpServletResponse;
15 14 import javax.servlet.http.HttpSession;
16 15  
17 16 import org.smart4j.framework.core.ConfigHelper;
18   -import org.smart4j.framework.orm.DataSet;
19 17  
20   -import com.cnlive.mz.live.LiveUtils;
21   -import com.cnlive.mz.live.entity.TActivity;
22   -import com.cnlive.mz.live.entity.TUser;
  18 +import com.cnlive.mz.live.common.LiveUtils;
23 19  
24 20 /*
25 21 *
... ...
src/main/resources/smart.properties
... ... @@ -8,7 +8,7 @@ smart.framework.custom.ds_factory=org.smart4j.plugin.dbcp.DbcpDataSourceFactory
8 8  
9 9 smart.framework.jdbc.type=mysql
10 10 smart.framework.jdbc.driver=com.mysql.jdbc.Driver
11   -smart.framework.jdbc.url=jdbc:mysql://101.251.198.175:3306/cnlive_live?autoReconnect=true&failOverReadOnly=false
  11 +smart.framework.jdbc.url=jdbc:mysql://124.193.218.90:3306/cnlive_live?autoReconnect=true&failOverReadOnly=false
12 12 smart.framework.jdbc.username=cnlive_oa
13 13 smart.framework.jdbc.password=H8rf#_3@ccx9(
14 14 #
... ...
src/main/webapp/pages/common/js.jsp
... ... @@ -23,7 +23,14 @@
23 23 <script src="${BASE}/static/assets/plugins/timepicker/bootstrap-timepicker.min.js" type="text/javascript"></script>
24 24 <!-- iCheck 1.0.1 -->
25 25 <script src="${BASE}/static/assets/plugins/iCheck/icheck.min.js" type="text/javascript"></script>
26   - <script src="${BASE}/static/assets/plugins/slimScroll/jquery.slimscroll.min.js" type="text/javascript"></script>
  26 +<script src="${BASE}/static/assets/plugins/slimScroll/jquery.slimscroll.min.js" type="text/javascript"></script>
  27 +
  28 +<link rel="stylesheet" href="${BASE}/static/assets/plugins/fileinput/fileinput.css" />
  29 +<link rel="stylesheet" href="${BASE}/static/assets/plugins/fileinput/fileinput.min.css" />
  30 +<script src="${BASE}/static/assets/plugins/fileinput/fileinput.js"></script>
  31 +<script src="${BASE}/static/assets/plugins/fileinput/fileinput.min.js"></script>
  32 +<script src="${BASE}/static/assets/plugins/fileinput/fileinput_locale_zh.js"></script>
  33 +
27 34 <!--###########-->
28 35 <script src="${BASE}/static/assets/cnlive/js/channel.js" type="text/javascript"></script>
29 36 <script src="${BASE}/static/assets/cnlive/js/signal.js" type="text/javascript"></script>
... ...
src/main/webapp/pages/common/left.jsp
... ... @@ -41,6 +41,15 @@
41 41 <li>
42 42 <a href="${BASE}/signal/list/1"><i class="fa fa-circle-o text-red"></i>信源管理</a>
43 43 </li>
  44 +
  45 + <!-- 主播 -->
  46 + <li class="header">系统设置</li>
  47 + <li>
  48 + <a href="${BASE}/room/list/1"><i class="fa fa-circle-o text-yellow"></i>直播间管理</a>
  49 + </li>
  50 + <li>
  51 + <a href="${BASE}/live/list/1"><i class="fa fa-circle-o text-yellow"></i>直播活动</a>
  52 + </li>
44 53 </c:if>
45 54 <c:if test="${sessionScope.roleId=='0'}">
46 55 <li class="header">导航栏</li>
... ...
src/main/webapp/pages/live/live_add.jsp 0 → 100644
  1 +<%@ page language="java" pageEncoding="UTF-8"%>
  2 +<%@ include file="/pages/common/taglib.jsp"%>
  3 +<!DOCTYPE html>
  4 +<html>
  5 +<head>
  6 +<meta charset="UTF-8">
  7 +<title>新建活动 | <f:message key="common.title" /></title>
  8 +<meta
  9 + content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no'
  10 + name='viewport'>
  11 +<%@ include file="/pages/common/css.jsp"%>
  12 +
  13 +<style type="text/css">
  14 + span.error{
  15 + padding-left: 15px;
  16 + color: red;
  17 + }
  18 + </style>
  19 +<link
  20 + href="http://www.bootcss.com/p/bootstrap-datetimepicker/bootstrap-datetimepicker/css/datetimepicker.css"
  21 + rel="stylesheet">
  22 + <script type="text/javascript" charset="utf-8" src="${BASE}/static/assets/ueditor/ueditor.config.js"></script>
  23 + <script type="text/javascript" charset="utf-8" src="${BASE}/static/assets/ueditor/ueditor.all.min.js"> </script>
  24 + <script type="text/javascript" charset="utf-8" src="${BASE}/static/assets/ueditor/lang/zh-cn/zh-cn.js"></script>
  25 +
  26 +</head>
  27 +<body class="skin-blue fixed ">
  28 + <div class="wrapper">
  29 + <%@ include file="/pages/common/top.jsp"%>
  30 + <%@ include file="/pages/common/left.jsp"%>
  31 + <div class="content-wrapper">
  32 + <section class="content-header">
  33 + <h1>${empty tActivity.id ? '新建活动':'编辑活动'}
  34 + <small>${tActivity.name}</small> <small class="label label-warning"
  35 + style="display: none" id="info_tab_span"><i
  36 + class="fa fa-bell-o"></i>保存成功</small>
  37 + </h1>
  38 + <ol class="breadcrumb">
  39 + <li><a><i class="fa fa-dashboard"></i> 首页</a></li>
  40 + <li class="active">新增活动</li>
  41 + </ol>
  42 + </section>
  43 + <!-- Main content -->
  44 + <section class="content">
  45 + <form id="create_form" enctype="multipart/form-data" method="post">
  46 + <div class="row">
  47 + <!-- right column -->
  48 + <div class="col-md-12">
  49 + <!-- general form elements disabled -->
  50 + <div class="box box-warning">
  51 + <div class="box-body">
  52 + <div class="form-group">
  53 + <label> 活动名称 </label>
  54 + <div class="input-group">
  55 + <span class="input-group-addon"><i class="fa fa-font"></i>
  56 + </span> <input type="text" value="${tActivity.name }" name="name"
  57 + id="name" class="form-control">
  58 + <input type="text" id="activity_id" name="activity_id" value="${tActivity.id}" hidden="">
  59 + </div>
  60 + </div>
  61 + <div class="form-group">
  62 + <label> 直播时间 </label>
  63 + <div class="row">
  64 + <div class="col-lg-6">
  65 + <div class="input-group">
  66 + <span class="input-group-addon"> 开始时间 </span> <input
  67 + type="text" class="form-control form_datetime"
  68 + value="<fmt:formatDate value="${tActivity.start_time}" pattern="yyyy-MM-dd HH:mm"/>"
  69 + name="start_time" id="start_time"
  70 + data-inputmask="'alias': 'yyyy-MM-dd HH:mm'" data-mask="" />
  71 + </div>
  72 + </div>
  73 + <div class="col-lg-6">
  74 + <div class="input-group">
  75 + <span class="input-group-addon"> 结束时间</span> <input
  76 + type="text" class="form-control form_datetime"
  77 + value="<fmt:formatDate value="${tActivity.end_time}" pattern="yyyy-MM-dd HH:mm"/>"
  78 + name="end_time" id="end_time"
  79 + data-inputmask="'alias': 'yyyy-MM-dd HH:mm'" data-mask="">
  80 + </div>
  81 + </div>
  82 + </div>
  83 + </div>
  84 + <div class="form-group">
  85 + <label>海报 </label>
  86 + <div class="input-group">
  87 + <span class="input-group-addon"><i
  88 + class="fa fa-file-word-o"></i> </span> <input id="input-22" type="file" name="input-22" accept="image/*" class="file-loading">
  89 + </div>
  90 + </div>
  91 + <div class="form-group">
  92 + <label> 播出直播间 </label>
  93 + <div class="box box-warning">
  94 + <div class="box-body">
  95 + <div class="form-group">
  96 + <select class="form-control" name="t_default_video_id"
  97 + id="t_default_video_id">
  98 + <c:forEach var="item" items="${tRooms}"
  99 + varStatus="stat">
  100 + <option id="t_room_id_${item.id}" ${item.id==tLive.t_room_id ? 'selected="selected"':''} value="${item.id}">${item.name}</option>
  101 + </c:forEach>
  102 + </select>
  103 + </div>
  104 + </div>
  105 + </div>>
  106 + </div>
  107 +
  108 + <div class="form-group">
  109 + <label>活动简述 </label>
  110 + <div class="input-group">
  111 + <span class="input-group-addon"><i
  112 + class="fa fa-file-word-o"></i> </span> <script id="editor" type="text/plain" style="width:1024px;height:500px;"></script>
  113 + </div>
  114 + </div>
  115 + <div class="box-footer">
  116 + <button type="button" id="t_activity_save_btn"
  117 + name="t_activity_save_btn" onclick="toSubmit();"
  118 + class="btn btn-success">
  119 + <i class="fa fa-save "></i> 保存
  120 + </button>
  121 + </div>
  122 + </div>
  123 + </div>
  124 + </div>
  125 + </div>
  126 + </form>
  127 + </div>
  128 + </section>
  129 + </div>
  130 + </div>
  131 + <%@ include file="/pages/common/bottom.jsp"%>
  132 +</div>
  133 + <!-- 信号选择结束 -->
  134 + <%@ include file="/pages/common/js.jsp"%>
  135 +
  136 + <script type="text/javascript">
  137 +
  138 + $(document).on('ready', function() {
  139 + $("#input-22").fileinput({
  140 + previewFileType: "image",
  141 + browseClass: "btn btn-success",
  142 + browseLabel: "Pick Image",
  143 + browseIcon: "<i class=\"glyphicon glyphicon-picture\"></i> ",
  144 + removeClass: "btn btn-danger",
  145 + removeLabel: "Delete",
  146 + removeIcon: "<i class=\"glyphicon glyphicon-trash\"></i> ",
  147 + uploadClass: "btn btn-info",
  148 + uploadLabel: "Upload",
  149 + uploadIcon: "<i class=\"glyphicon glyphicon-upload\"></i> "
  150 + });
  151 + });
  152 +
  153 +
  154 + $(function () {
  155 + //Money Euro
  156 + $("[data-mask]").inputmask();
  157 + });
  158 +
  159 + $(function () {
  160 + $("#datemask").inputmask("dd/mm/yyyy", {"placeholder": "dd/mm/yyyy"});
  161 + //Datemask2 mm/dd/yyyy
  162 + $("#datemask2").inputmask("mm/dd/yyyy", {"placeholder": "mm/dd/yyyy"});
  163 + //Money Euro
  164 + $("[data-mask]").inputmask();
  165 +
  166 + //Date range picker
  167 + $('#reservation').daterangepicker();
  168 + //Date range picker with time picker
  169 + $('#reservationtime').daterangepicker({timePicker: true, timePickerIncrement: 30, format: 'MM/DD/YYYY h:mm A'});
  170 + //Date range as a button
  171 + $('#daterange-btn').daterangepicker(
  172 + {
  173 + ranges: {
  174 + 'Today': [moment(), moment()],
  175 + 'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],
  176 + 'Last 7 Days': [moment().subtract('days', 6), moment()],
  177 + 'Last 30 Days': [moment().subtract('days', 29), moment()],
  178 + 'This Month': [moment().startOf('month'), moment().endOf('month')],
  179 + 'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]
  180 + },
  181 + startDate: moment().subtract('days', 29),
  182 + endDate: moment()
  183 + },
  184 + function (start, end) {
  185 + $('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
  186 + }
  187 + );
  188 + });
  189 + </script>
  190 +
  191 +
  192 + <!-- Le javascript
  193 + ================================================== -->
  194 + <script
  195 + src="http://www.bootcss.com/p/bootstrap-datetimepicker/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js"></script>
  196 +
  197 + <script type="text/javascript">
  198 + $(".form_datetime").datetimepicker({
  199 + //format: "dd MM yyyy - hh:ii",
  200 + format: "yyyy-mm-dd hh:ii",
  201 + autoclose: true,
  202 + todayBtn: true,
  203 + pickerPosition: "bottom-right"
  204 + });
  205 +</script>
  206 +
  207 +<script type="text/javascript">
  208 +
  209 + //实例化编辑器
  210 + //建议使用工厂方法getEditor创建和引用编辑器实例,如果在某个闭包下引用该编辑器,直接调用UE.getEditor('editor')就能拿到相关的实例
  211 + var ue = UE.getEditor('editor',{
  212 + autoHeightEnabled: true,
  213 + autoFloatEnabled: true
  214 + });
  215 +
  216 +
  217 + function isFocus(e){
  218 + alert(UE.getEditor('editor').isFocus());
  219 + UE.dom.domUtils.preventDefault(e)
  220 + }
  221 + function setblur(e){
  222 + UE.getEditor('editor').blur();
  223 + UE.dom.domUtils.preventDefault(e)
  224 + }
  225 + function insertHtml() {
  226 + var value = prompt('插入html代码', '');
  227 + UE.getEditor('editor').execCommand('insertHtml', value)
  228 + }
  229 + function createEditor() {
  230 + enableBtn();
  231 + UE.getEditor('editor');
  232 + }
  233 + function getAllHtml() {
  234 + alert(UE.getEditor('editor').getAllHtml())
  235 + }
  236 + function getContent() {
  237 + var arr = [];
  238 + arr.push("使用editor.getContent()方法可以获得编辑器的内容");
  239 + arr.push("内容为:");
  240 + arr.push(UE.getEditor('editor').getContent());
  241 + alert(arr.join("\n"));
  242 + }
  243 + function getPlainTxt() {
  244 + var arr = [];
  245 + arr.push("使用editor.getPlainTxt()方法可以获得编辑器的带格式的纯文本内容");
  246 + arr.push("内容为:");
  247 + arr.push(UE.getEditor('editor').getPlainTxt());
  248 + alert(arr.join('\n'))
  249 + }
  250 + function setContent(isAppendTo) {
  251 + var arr = [];
  252 + arr.push("使用editor.setContent('欢迎使用ueditor')方法可以设置编辑器的内容");
  253 + UE.getEditor('editor').setContent('欢迎使用ueditor', isAppendTo);
  254 + alert(arr.join("\n"));
  255 + }
  256 + function setDisabled() {
  257 + UE.getEditor('editor').setDisabled('fullscreen');
  258 + disableBtn("enable");
  259 + }
  260 +
  261 + function setEnabled() {
  262 + UE.getEditor('editor').setEnabled();
  263 + enableBtn();
  264 + }
  265 +
  266 + function getText() {
  267 + //当你点击按钮时编辑区域已经失去了焦点,如果直接用getText将不会得到内容,所以要在选回来,然后取得内容
  268 + var range = UE.getEditor('editor').selection.getRange();
  269 + range.select();
  270 + var txt = UE.getEditor('editor').selection.getText();
  271 + alert(txt)
  272 + }
  273 +
  274 + function getContentTxt() {
  275 + var arr = [];
  276 + arr.push("使用editor.getContentTxt()方法可以获得编辑器的纯文本内容");
  277 + arr.push("编辑器的纯文本内容为:");
  278 + arr.push(UE.getEditor('editor').getContentTxt());
  279 + alert(arr.join("\n"));
  280 + }
  281 + function hasContent() {
  282 + var arr = [];
  283 + arr.push("使用editor.hasContents()方法判断编辑器里是否有内容");
  284 + arr.push("判断结果为:");
  285 + arr.push(UE.getEditor('editor').hasContents());
  286 + alert(arr.join("\n"));
  287 + }
  288 + function setFocus() {
  289 + UE.getEditor('editor').focus();
  290 + }
  291 + function deleteEditor() {
  292 + disableBtn();
  293 + UE.getEditor('editor').destroy();
  294 + }
  295 + function disableBtn(str) {
  296 + var div = document.getElementById('btns');
  297 + var btns = UE.dom.domUtils.getElementsByTagName(div, "button");
  298 + for (var i = 0, btn; btn = btns[i++];) {
  299 + if (btn.id == str) {
  300 + UE.dom.domUtils.removeAttributes(btn, ["disabled"]);
  301 + } else {
  302 + btn.setAttribute("disabled", "true");
  303 + }
  304 + }
  305 + }
  306 + function enableBtn() {
  307 + var div = document.getElementById('btns');
  308 + var btns = UE.dom.domUtils.getElementsByTagName(div, "button");
  309 + for (var i = 0, btn; btn = btns[i++];) {
  310 + UE.dom.domUtils.removeAttributes(btn, ["disabled"]);
  311 + }
  312 + }
  313 +
  314 + function getLocalData () {
  315 + alert(UE.getEditor('editor').execCommand( "getlocaldata" ));
  316 + }
  317 +
  318 + function clearLocalData () {
  319 + UE.getEditor('editor').execCommand( "clearlocaldata" );
  320 + alert("已清空草稿箱")
  321 + }
  322 +
  323 +
  324 + $(function() {
  325 + $('#create_form').ajaxForm({
  326 + type : 'post',
  327 + url : '../live/save',
  328 + enctype : 'multipart/form-data',
  329 + beforeSubmit : function() {
  330 + return true;
  331 + },
  332 + error : function(XMLHttpRequest, textStatus, errorThrown) {
  333 + alert("错误");
  334 + },
  335 + success : function(result) {
  336 + location.href = '../live/list/1';
  337 + }
  338 + });
  339 + });
  340 +
  341 +
  342 +</script>
  343 +</body>
  344 +</html>
... ...
src/main/webapp/pages/live/live_management.jsp 0 → 100644
  1 +<%@ page language="java" pageEncoding="UTF-8"%>
  2 +<%@ include file="/pages/common/taglib.jsp"%>
  3 +<!DOCTYPE html>
  4 +<html>
  5 +<head>
  6 +<meta charset="UTF-8">
  7 +<title>活动管理 | <f:message key="common.title" /></title>
  8 +<meta
  9 + content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no'
  10 + name='viewport'>
  11 +<%@ include file="/pages/common/css.jsp"%>
  12 +</head>
  13 +<body class="skin-blue fixed ">
  14 + <div class="wrapper">
  15 + <%@ include file="/pages/common/top.jsp"%>
  16 + <%@ include file="/pages/common/left.jsp"%>
  17 + <div class="content-wrapper">
  18 + <!-- Content Header (Page header) -->
  19 + <section class="content-header">
  20 + <h1>
  21 + 活动管理<small><a href="../../live/preload"><i
  22 + class="fa fa-plus"></i>新增活动</a> </small>
  23 + <small class="label label-warning" style="display: none"
  24 + id="info_tab_span"><i class="fa fa-bell-o"></i></small>
  25 + </h1>
  26 +
  27 + <ol class="breadcrumb">
  28 + <li><a><i class="fa fa-dashboard"></i> 首页</a></li>
  29 + <li class="active">活动管理</li>
  30 + </ol>
  31 + </section>
  32 + <!-- Main content -->
  33 + <section class="content">
  34 + <div class="row">
  35 + <div class="col-xs-12">
  36 + <div class="box box-warning">
  37 + <div class="box-header with-border">
  38 + <h3 class="box-title"></h3>
  39 + <div class="box-tools">
  40 + <div class="input-group">
  41 + <form action="../search/1" method="post">
  42 + <div class="input-group">
  43 + <input type="text" name="search_text" id="search_text"
  44 + class="form-control input-sm" style="width: 150px;"
  45 + placeholder="Search" />
  46 + <button id="t_activity_search_btn" type="submit"
  47 + class="btn btn-sm btn-default">
  48 + <i class="fa fa-search"></i>搜索
  49 + </button>
  50 + </div>
  51 + </form>
  52 + </div>
  53 + </div>
  54 + </div>
  55 + <!-- /.box-header -->
  56 + <div class="box-body">
  57 + <table class="table table-bordered">
  58 + <tr>
  59 + <th>活动名称</th>
  60 + <th>开始时间</th>
  61 + <th>结束时间</th>
  62 + <th>状态</th>
  63 + <th>修改</th>
  64 + <th>删除</th>
  65 + </tr>
  66 + <c:forEach var="item" items="${tLive.recordList}"
  67 + varStatus="stat">
  68 + <tr>
  69 + <td><a href="${BASE}/activity/preview/${item.id}">${item.title}</a>
  70 + </td>
  71 + <td><fmt:formatDate value="${item.start_time}"
  72 + pattern="yyyy-MM-dd HH:mm" /></td>
  73 + <td>${item.end_time}</td>
  74 + <td>
  75 +
  76 + </td>
  77 + <td>
  78 + <button class="btn btn-default btn-sm"
  79 + onclick="t_activity_edit(${item.id});">
  80 + <i class="fa fa-edit"></i>
  81 + </button>
  82 + </td>
  83 + <td>
  84 + <button class="btn btn-danger btn-sm"
  85 + onclick="t_activity_delete(${item.id});">
  86 + <i class="fa fa-close"></i>
  87 + </button>
  88 + </td>
  89 + </tr>
  90 + </c:forEach>
  91 + </table>
  92 + </div>
  93 + <!-- /.box-body -->
  94 + <div class="box-footer clearfix">
  95 + <center>
  96 + <tag:pager id="product_pager" pager="${tLive}" />
  97 + </center>
  98 + </div>
  99 + </div>
  100 + </div>
  101 + </div>
  102 + </div>
  103 + <%@ include file="/pages/common/bottom.jsp"%>
  104 + </div>
  105 + <%@ include file="/pages/common/js.jsp"%>
  106 +</body>
  107 +</html>
... ...
src/main/webapp/pages/room/room_add.jsp 0 → 100644
  1 +<%@ page language="java" pageEncoding="UTF-8"%>
  2 +<%@ include file="/pages/common/taglib.jsp"%>
  3 +<!DOCTYPE html>
  4 +<html>
  5 +<head>
  6 +<meta charset="UTF-8">
  7 +<title>新建直播间 | <f:message key="common.title" /></title>
  8 +<meta
  9 + content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no'
  10 + name='viewport'>
  11 +<%@ include file="/pages/common/css.jsp"%>
  12 +<link href="${BASE}/static/assets/plugins/uploadfile/css/fileinput.css"
  13 + media="all" rel="stylesheet" type="text/css" />
  14 +<!--[if IE]>
  15 + <script src="http://libs.useso.com/js/html5shiv/3.7/html5shiv.min.js"></script>
  16 + <![endif]-->
  17 +</head>
  18 +<body class="skin-blue sidebar-mini">
  19 + <div class="wrapper">
  20 + <%@ include file="/pages/common/top.jsp"%>
  21 + <%@ include file="/pages/common/left.jsp"%>
  22 + <div class="content-wrapper">
  23 + <!-- Content Header (Page header) -->
  24 + <section class="content-header">
  25 + <h1>
  26 + ${empty tRoom.id ? '新建直播间':'编辑直播间'} <small>${tRoom.name}</small> <small
  27 + class="label label-warning" style="display: none"
  28 + id="info_tab_span"><i class="fa fa-bell-o"></i>保存成功</small>
  29 + </h1>
  30 + <ol class="breadcrumb">
  31 + <li><a><i class="fa fa-dashboard"></i> 首页</a></li>
  32 + <li class="active">新增直播间</li>
  33 + </ol>
  34 + </section>
  35 + <!-- Main content -->
  36 + <section class="content">
  37 + <div class="row">
  38 + <div class="col-md-12">
  39 + <form id="create_form" enctype="multipart/form-data" method="post">
  40 + <div class="box box-success">
  41 + <div class="box-body">
  42 + <div class="form-group">
  43 + <label>直播间名称 </label>
  44 + <div class="input-group">
  45 + <span class="input-group-addon"><i class="fa fa-font"></i>
  46 + </span> <input type="text" class="form-control"
  47 + value="${tRoom.name}" id="name" name="name">
  48 + </div>
  49 + </div>
  50 + <div class="form-group">
  51 + <label>海报 </label>
  52 + <div class="input-group">
  53 + <div class="input-group-addon">
  54 + <i class="fa fa-file-image-o"></i>
  55 + </div>
  56 + <input id="input-22" type="file" name="input-22"
  57 + accept="image/*" class="file-loading">
  58 + </div>
  59 + </div>
  60 + </div>
  61 + <button type="submit" id="t_channel_save_btn"
  62 + class="btn btn-primary">
  63 + <i class="fa fa-save "></i> 保存
  64 + </button>
  65 + </form>
  66 + </div>
  67 + </div>
  68 + </section>
  69 + </div>
  70 + <%@ include file="/pages/common/bottom.jsp"%>
  71 + </div>
  72 + <%@ include file="/pages/common/js.jsp"%>
  73 + <script src="${BASE}/static/assets/cnlive/js/Math.uuid.js"></script>
  74 + <script src="${BASE}/static/assets/cnlive/js/ajax_rest.js"></script>
  75 + <script
  76 + src="${BASE}/static/assets/cnlive/js/validate/validate_channel.js"
  77 + type="text/javascript"></script>
  78 + <script src="${BASE}/static/assets/plugins/uploadfile/js/fileinput.js"
  79 + type="text/javascript"></script>
  80 + <script
  81 + src="${BASE}/static/assets/plugins/uploadfile/js/fileinput_locale_zh.js"
  82 + type="text/javascript"></script>
  83 +
  84 + <script type="text/javascript">
  85 + $(document).on('ready', function() {
  86 + $("#input-22").fileinput({
  87 + previewFileType: "image",
  88 + browseClass: "btn btn-success",
  89 + browseLabel: "Pick Image",
  90 + browseIcon: "<i class=\"glyphicon glyphicon-picture\"></i> ",
  91 + removeClass: "btn btn-danger",
  92 + removeLabel: "Delete",
  93 + removeIcon: "<i class=\"glyphicon glyphicon-trash\"></i> ",
  94 + uploadClass: "btn btn-info",
  95 + uploadLabel: "Upload",
  96 + uploadIcon: "<i class=\"glyphicon glyphicon-upload\"></i> "
  97 + });
  98 + });
  99 +
  100 + $(function() {
  101 + $('#create_form').ajaxForm({
  102 + type : 'post',
  103 + url : '../live/save',
  104 + enctype : 'multipart/form-data',
  105 + beforeSubmit : function() {
  106 + return true;
  107 + },
  108 + error : function(XMLHttpRequest, textStatus, errorThrown) {
  109 + alert("错误");
  110 + },
  111 + success : function(result) {
  112 + location.href = '../live/list/1';
  113 + }
  114 + });
  115 + });
  116 +
  117 + </script>
  118 +</body>
  119 +</html>
... ...
src/main/webapp/pages/room/room_management.jsp 0 → 100644
  1 +<%@ page language="java" pageEncoding="UTF-8"%>
  2 +<%@ include file="/pages/common/taglib.jsp"%>
  3 +<!DOCTYPE html>
  4 +<html>
  5 +<head>
  6 +<meta charset="UTF-8">
  7 +<title>直播间管理 | <f:message key="common.title"/></title>
  8 +<meta
  9 + content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no'
  10 + name='viewport'>
  11 +<%@ include file="/pages/common/css.jsp"%>
  12 +</head>
  13 +<body class="skin-blue sidebar-mini">
  14 + <div class="wrapper">
  15 + <%@ include file="/pages/common/top.jsp"%>
  16 + <%@ include file="/pages/common/left.jsp"%>
  17 + <div class="content-wrapper">
  18 + <!-- Content Header (Page header) -->
  19 + <section class="content-header">
  20 + <h1>
  21 + 直播间管理 <small><a href="../../room/pload"><i
  22 + class="fa fa-plus"></i>新增直播间</a> </small>
  23 + <small class="label label-warning" style="display: none"
  24 + id="info_tab_span"><i class="fa fa-bell-o"></i></small>
  25 + </h1>
  26 + <ol class="breadcrumb">
  27 + <li><a><i class="fa fa-dashboard"></i> 首页</a></li>
  28 + <li><a>直播间管理</a></li>
  29 + </ol>
  30 + </section>
  31 + <!-- Main content -->
  32 + <section class="content">
  33 + <div class="row">
  34 + <div class="col-xs-12">
  35 + <div class="box box-success">
  36 + <div class="box-header with-border">
  37 + <!-- <h3 class="box-title"></h3> -->
  38 + <div class="box-tools">
  39 + <div class="input-group">
  40 + </div>
  41 + </div>
  42 + </div>
  43 + <!-- /.box-header -->
  44 + <div class="box-body">
  45 + <table class="table table-bordered">
  46 + <tr>
  47 + <th>名称</th>
  48 + <th>状态</th>
  49 + <th>stream name</th>
  50 + <th>修改</th>
  51 + <th>删除</th>
  52 + </tr>
  53 + <c:forEach var="item" items="${tRooms.recordList}"
  54 + varStatus="stat">
  55 + <tr>
  56 + <td> ${item.name}</td>
  57 + <td> ${item.t_status_id}</td>
  58 + <td>${item.stream_name}</td>
  59 + <td>
  60 + <button class="btn btn-default btn-sm"
  61 + onclick="t_channel_edit(${item.id});">
  62 + <i class="fa fa-edit"></i>
  63 + </button>
  64 + </td>
  65 + <td>
  66 + <button class="btn btn-danger btn-sm"
  67 + onclick="t_channel_delete(${item.id});">
  68 + <i class="fa fa-close"></i>
  69 + </button>
  70 + </td>
  71 + </tr>
  72 + </c:forEach>
  73 + </table>
  74 + </div>
  75 + <!-- /.box-body -->
  76 + <div class="box-footer clearfix ">
  77 + <center>
  78 + <tag:pager id="product_pager" pager="${tRooms}" />
  79 + </center>
  80 + </div>
  81 + </div>
  82 + <!-- /.box -->
  83 + </div>
  84 + </div>
  85 + </div>
  86 + <%@ include file="/pages/common/bottom.jsp"%>
  87 + </div>
  88 + <%@ include file="/pages/common/js.jsp"%>
  89 +</body>
  90 +</html>
... ...
src/main/webapp/pages/room/room_preview.jsp 0 → 100644
  1 +<%@ page language="java" pageEncoding="UTF-8"%>
  2 +<%@ include file="/pages/common/taglib.jsp"%>
  3 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  4 +<html>
  5 +<head>
  6 +<meta charset="UTF-8">
  7 +<title>直播间预览 | <f:message key="common.title"/></title>
  8 +<meta
  9 + content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no'
  10 + name='viewport'>
  11 +<%@ include file="/pages/common/css.jsp"%>
  12 +<script src="${BASE}/static/assets/jwplayer/jwplayer.js"></script>
  13 +<script src="${BASE}/static/assets/jwplayer/jwplayer.html5.js"></script>
  14 +<script type="text/javascript">
  15 + jwplayer.key = "MGAzpXRYxGnaVXhH8jSdKXzDe7ucAAvZGWggIA==";
  16 +</script>
  17 +</head>
  18 +
  19 +<body class="skin-blue fixed sidebar-mini">
  20 + <div class="wrapper">
  21 + <%@ include file="/pages/common/top.jsp"%>
  22 + <%@ include file="/pages/common/left.jsp"%>
  23 + <!-- Content Wrapper. Contains page content -->
  24 + <div class="content-wrapper">
  25 + <!-- Content Header (Page header) -->
  26 + <section class="content-header">
  27 + <h1>频道预览<small>${tChannel.name_zh}</small></h1>
  28 + <ol class="breadcrumb">
  29 + <li><a><i class="fa fa-dashboard"></i> 首页</a></li>
  30 + <li><a href="../list/1">频道管理</a></li>
  31 + <li class="active">新增预览</li>
  32 + </ol>
  33 + </section>
  34 + <section class="content">
  35 + <div class="row">
  36 + <div class="col-md-6">
  37 + <div class="box">
  38 + <div class="box-header with-border">
  39 + <h3 class="box-title">${isLive==true ? '直播活动信号':'滚播信号'}</h3>
  40 + </div>
  41 + <div class="box-body">
  42 + <input type="hidden" name="play_url_1" id="play_url_1"
  43 + value="${tWowzaSignalBean.tWowzaStream.publish_url}" /> <span
  44 + class="mailbox-attachment-icon has-img" id="player_span_1">
  45 + Loading the player... </span>
  46 + </div>
  47 + <div class="mailbox-attachment-info">
  48 + <a class="mailbox-attachment-name">stream_name:${tWowzaSignalBean.tWowzaStream.stream_name}<br>application_name:${tWowzaSignalBean.tWowzaStream.application_name } <br>lan_ip:${tWowzaSignalBean.tWowza.lan_ip } </a>
  49 +
  50 + </div>
  51 + <div class="box-footer clearfix">
  52 + <!-- <ul class="pagination pagination-sm no-margin pull-right">
  53 + <li>
  54 + <button class="btn btn-info btn-sm" id="play_button_1"
  55 + onclick="play_1();">载入/断开</button>
  56 + </li>
  57 + </ul> -->
  58 + </div>
  59 + </div>
  60 + </div>
  61 +
  62 + <div class="col-md-6">
  63 + <div class="box">
  64 + <div class="box-header with-border">
  65 + <h3 class="box-title">ips 播放地址</h3>
  66 + </div>
  67 + <div class="box-body">
  68 + <input type="hidden" name="play_url_2" id="play_url_2"
  69 + value="${tChannel.play_url}" /> <span
  70 + class="mailbox-attachment-icon has-img" id="player_span_2">
  71 + Loading the player... </span>
  72 + </div>
  73 + <div class="mailbox-attachment-info">
  74 + <a class="mailbox-attachment-name"> </a>
  75 + </div>
  76 + <div class="box-footer clearfix">
  77 + <!-- <ul class="pagination pagination-sm no-margin pull-right">
  78 + <li>
  79 + <button class="btn btn-info btn-sm" id="play_button_2"
  80 + onclick="play_2();">载入/断开</button>
  81 + </li>
  82 + </ul> -->
  83 + </div>
  84 + </div>
  85 + </div>
  86 + </div>
  87 + </div>
  88 + </section>
  89 + </div>
  90 + <%@ include file="/pages/common/bottom.jsp"%>
  91 + <%@ include file="/pages/common/js.jsp"%>
  92 + <script src="${BASE}/static/assets/cnlive/js/player_2.js"></script>
  93 +</body>
  94 +</html>
... ...
src/main/webapp/static/assets/plugins/fileinput/fileinput.css 0 → 100644
  1 +/*!
  2 + * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014 - 2015
  3 + * @package bootstrap-fileinput
  4 + * @version 4.2.9
  5 + *
  6 + * File input styling for Bootstrap 3.0
  7 + * Built for Yii Framework 2.0
  8 + * Author: Kartik Visweswaran
  9 + * Year: 2015
  10 + * For more Yii related demos visit http://demos.krajee.com
  11 + */
  12 +.file-loading {
  13 + top: 0;
  14 + right: 0;
  15 + width: 25px;
  16 + height: 25px;
  17 + font-size: 999px;
  18 + text-align: right;
  19 + color: #fff;
  20 + background: transparent url('../img/loading.gif') top left no-repeat;
  21 + border: none;
  22 +}
  23 +
  24 +.file-object {
  25 + margin: 0 0 -5px 0;
  26 + padding: 0;
  27 +}
  28 +
  29 +.btn-file {
  30 + position: relative;
  31 + overflow: hidden;
  32 +}
  33 +
  34 +.btn-file input[type=file] {
  35 + position: absolute;
  36 + top: 0;
  37 + right: 0;
  38 + min-width: 100%;
  39 + min-height: 100%;
  40 + text-align: right;
  41 + opacity: 0;
  42 + background: none repeat scroll 0 0 transparent;
  43 + cursor: inherit;
  44 + display: block;
  45 +}
  46 +
  47 +.file-caption-name {
  48 + display: inline-block;
  49 + overflow: hidden;
  50 + height: 20px;
  51 + word-break: break-all;
  52 +}
  53 +
  54 +.input-group-lg .file-caption-name {
  55 + height: 25px;
  56 +}
  57 +
  58 +.file-preview-detail-modal {
  59 + text-align: left;
  60 +}
  61 +
  62 +.file-error-message {
  63 + color: #a94442;
  64 + background-color: #f2dede;
  65 + margin: 5px;
  66 + border: 1px solid #ebccd1;
  67 + border-radius: 4px;
  68 + padding: 15px;
  69 +}
  70 +
  71 +.file-error-message pre, .file-error-message ul {
  72 + margin: 0;
  73 + text-align: left;
  74 +}
  75 +
  76 +.file-error-message pre {
  77 + margin: 5px 0;
  78 +}
  79 +
  80 +.file-caption-disabled {
  81 + background-color: #EEEEEE;
  82 + cursor: not-allowed;
  83 + opacity: 1;
  84 +}
  85 +
  86 +.file-preview {
  87 + border-radius: 5px;
  88 + border: 1px solid #ddd;
  89 + padding: 5px;
  90 + width: 100%;
  91 + margin-bottom: 5px;
  92 +}
  93 +
  94 +.file-preview-frame {
  95 + display: table;
  96 + margin: 8px;
  97 + height: 160px;
  98 + border: 1px solid #ddd;
  99 + box-shadow: 1px 1px 5px 0 #a2958a;
  100 + padding: 6px;
  101 + float: left;
  102 + text-align: center;
  103 + vertical-align: middle;
  104 +}
  105 +
  106 +.file-preview-frame:not(.file-preview-error):hover {
  107 + box-shadow: 3px 3px 5px 0 #333;
  108 +}
  109 +
  110 +.file-preview-image {
  111 + height: 160px;
  112 + vertical-align: middle;
  113 +}
  114 +
  115 +.file-preview-text {
  116 + text-align: left;
  117 + width: 160px;
  118 + margin-bottom: 2px;
  119 + color: #428bca;
  120 + background: #fff;
  121 + overflow-x: hidden;
  122 +}
  123 +
  124 +.file-preview-other {
  125 + display: table-cell;
  126 + text-align: center;
  127 + vertical-align: middle;
  128 + width: 160px;
  129 + height: 160px;
  130 + border: 2px solid #999;
  131 + border-radius: 30px;
  132 +}
  133 +
  134 +.file-preview-other:hover {
  135 + opacity: 0.8;
  136 +}
  137 +
  138 +.file-actions, .file-other-error {
  139 + text-align: left;
  140 +}
  141 +
  142 +.file-icon-lg {
  143 + font-size: 1.2em;
  144 +}
  145 +
  146 +.file-icon-2x {
  147 + font-size: 2.4em;
  148 +}
  149 +
  150 +.file-icon-4x {
  151 + font-size: 4.8em;
  152 +}
  153 +
  154 +.file-input-new .file-preview, .file-input-new .close, .file-input-new .glyphicon-file,
  155 +.file-input-new .fileinput-remove-button, .file-input-new .fileinput-upload-button,
  156 +.file-input-ajax-new .fileinput-remove-button, .file-input-ajax-new .fileinput-upload-button {
  157 + display: none;
  158 +}
  159 +
  160 +.file-thumb-loading {
  161 + background: transparent url('../img/loading.gif') no-repeat scroll center center content-box !important;
  162 +}
  163 +
  164 +.file-actions {
  165 + margin-top: 15px;
  166 +}
  167 +
  168 +.file-footer-buttons {
  169 + float: right;
  170 +}
  171 +
  172 +.file-upload-indicator {
  173 + padding-top: 2px;
  174 + cursor: default;
  175 + opacity: 0.8;
  176 + width: 60%;
  177 +}
  178 +
  179 +.file-upload-indicator:hover {
  180 + font-weight: bold;
  181 + opacity: 1;
  182 +}
  183 +
  184 +.file-footer-caption {
  185 + display: block;
  186 + white-space: nowrap;
  187 + overflow: hidden;
  188 + text-overflow: ellipsis;
  189 + width: 160px;
  190 + text-align: center;
  191 + padding-top: 4px;
  192 + font-size: 11px;
  193 + color: #777;
  194 + margin: 5px auto 10px auto;
  195 +}
  196 +
  197 +.file-preview-error {
  198 + opacity: 0.65;
  199 + box-shadow: none;
  200 +}
  201 +
  202 +.file-preview-frame:not(.file-preview-error) .file-footer-caption:hover {
  203 + color: #000;
  204 +}
  205 +
  206 +.file-drop-zone {
  207 + border: 1px dashed #aaa;
  208 + border-radius: 4px;
  209 + height: 100%;
  210 + text-align: center;
  211 + vertical-align: middle;
  212 + margin: 12px 15px 12px 12px;
  213 + padding: 5px;
  214 +}
  215 +
  216 +.file-drop-zone-title {
  217 + color: #aaa;
  218 + font-size: 40px;
  219 + padding: 85px 10px;
  220 +}
  221 +
  222 +.file-highlighted {
  223 + border: 2px dashed #999 !important;
  224 + background-color: #f0f0f0;
  225 +}
  226 +
  227 +.file-uploading {
  228 + background: url('../img/loading-sm.gif') no-repeat center bottom 10px;
  229 + opacity: 0.65;
  230 +}
  231 +
  232 +.file-thumb-progress .progress, .file-thumb-progress .progress-bar {
  233 + height: 10px;
  234 + font-size: 9px;
  235 + line-height: 10px;
  236 +}
  237 +
  238 +.file-thumbnail-footer {
  239 + position: relative;
  240 +}
  241 +
  242 +.file-thumb-progress {
  243 + position: absolute;
  244 + top: 22px;
  245 + left: 0;
  246 + right: 0;
  247 +}
  248 +
  249 +/* IE 10 fix */
  250 +.btn-file ::-ms-browse {
  251 + width:100%;
  252 + height:100%;
  253 +}
0 254 \ No newline at end of file
... ...
src/main/webapp/static/assets/plugins/fileinput/fileinput.js 0 → 100644
  1 +/*!
  2 + * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014 - 2015
  3 + * @version 4.2.9
  4 + *
  5 + * File input styled for Bootstrap 3.0 that utilizes HTML5 File Input's advanced
  6 + * features including the FileReader API.
  7 + *
  8 + * The plugin drastically enhances the HTML file input to preview multiple files on the client before
  9 + * upload. In addition it provides the ability to preview content of images, text, videos, audio, html,
  10 + * flash and other objects. It also offers the ability to upload and delete files using AJAX, and add
  11 + * files in batches (i.e. preview, append, or remove before upload).
  12 + *
  13 + * Author: Kartik Visweswaran
  14 + * Copyright: 2015, Kartik Visweswaran, Krajee.com
  15 + * For more JQuery plugins visit http://plugins.krajee.com
  16 + * For more Yii related demos visit http://demos.krajee.com
  17 + */
  18 +(function (factory) {
  19 + "use strict";
  20 + if (typeof define === 'function' && define.amd) { // jshint ignore:line
  21 + // AMD. Register as an anonymous module.
  22 + define(['jquery'], factory); // jshint ignore:line
  23 + } else { // noinspection JSUnresolvedVariable
  24 + if (typeof module === 'object' && module.exports) { // jshint ignore:line
  25 + // Node/CommonJS
  26 + // noinspection JSUnresolvedVariable
  27 + module.exports = factory(require('jquery')); // jshint ignore:line
  28 + } else {
  29 + // Browser globals
  30 + factory(window.jQuery);
  31 + }
  32 + }
  33 +}(function ($) {
  34 + "use strict";
  35 +
  36 + $.fn.fileinputLocales = {};
  37 +
  38 + var isIE, isEdge, handler, previewCache, getNum, hasFileAPISupport, hasDragDropSupport, hasFileUploadSupport, addCss,
  39 + STYLE_SETTING, OBJECT_PARAMS, DEFAULT_PREVIEW, defaultFileActionSettings, tMain1, tMain2, tPreview, tIcon, tClose,
  40 + tCaption, tBtnDefault, tBtnLink, tBtnBrowse, tModal, tProgress, tFooter, tActions, tActionDelete, tActionUpload,
  41 + tZoom, tGeneric, tHtml, tImage, tText, tVideo, tAudio, tFlash, tObject, tOther, defaultLayoutTemplates,
  42 + defaultPreviewTemplates, defaultPreviewTypes, defaultPreviewSettings, defaultFileTypeSettings, isEmpty, isArray,
  43 + isSet, getElement, uniqId, htmlEncode, replaceTags, objUrl, FileInput;
  44 +
  45 + isIE = function (ver) {
  46 + // check for IE versions < 11
  47 + if (navigator.appName !== 'Microsoft Internet Explorer') {
  48 + return false;
  49 + }
  50 + if (ver === 10) {
  51 + return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
  52 + }
  53 + var div = document.createElement("div"), status;
  54 + div.innerHTML = "<!--[if IE " + ver + "]> <i></i> <![endif]-->";
  55 + status = div.getElementsByTagName("i").length;
  56 + document.body.appendChild(div);
  57 + div.parentNode.removeChild(div);
  58 + return status;
  59 + };
  60 + isEdge = function () {
  61 + return new RegExp('Edge\/[0-9]+', 'i').test(navigator.userAgent);
  62 + };
  63 + handler = function ($el, event, callback, skipNS) {
  64 + var ev = skipNS ? event : event + '.fileinput';
  65 + $el.off(ev).on(ev, callback);
  66 + };
  67 + previewCache = {
  68 + data: {},
  69 + init: function (obj) {
  70 + var content = obj.initialPreview, id = obj.id;
  71 + if (content.length > 0 && !isArray(content)) {
  72 + content = content.split(obj.initialPreviewDelimiter);
  73 + }
  74 + previewCache.data[id] = {
  75 + content: content,
  76 + config: obj.initialPreviewConfig,
  77 + tags: obj.initialPreviewThumbTags,
  78 + delimiter: obj.initialPreviewDelimiter,
  79 + template: obj.previewGenericTemplate,
  80 + msg: function (n) {
  81 + return obj.getMsgSelected(n);
  82 + },
  83 + initId: obj.previewInitId,
  84 + footer: obj.getLayoutTemplate('footer').replace(/\{progress}/g, obj.renderThumbProgress()),
  85 + isDelete: obj.initialPreviewShowDelete,
  86 + caption: obj.initialCaption,
  87 + actions: function (showUpload, showDelete, disabled, url, key) {
  88 + return obj.renderFileActions(showUpload, showDelete, disabled, url, key);
  89 + }
  90 + };
  91 + },
  92 + fetch: function (id) {
  93 + return previewCache.data[id].content.filter(function (n) {
  94 + return n !== null;
  95 + });
  96 + },
  97 + count: function (id, all) {
  98 + return !!previewCache.data[id] && !!previewCache.data[id].content ?
  99 + (all ? previewCache.data[id].content.length : previewCache.fetch(id).length) : 0;
  100 + },
  101 + get: function (id, i, isDisabled) {
  102 + var ind = 'init_' + i, data = previewCache.data[id], config = data.config[i],
  103 + previewId = data.initId + '-' + ind, out, $tmp, frameClass = ' file-preview-initial';
  104 + /** @namespace config.frameClass */
  105 + /** @namespace config.frameAttr */
  106 + isDisabled = isDisabled === undefined ? true : isDisabled;
  107 + if (data.content[i] === null) {
  108 + return '';
  109 + }
  110 + if (!isEmpty(config) && !isEmpty(config.frameClass)) {
  111 + frameClass += ' ' + config.frameClass;
  112 + }
  113 + out = data.template
  114 + .replace(/\{previewId}/g, previewId)
  115 + .replace(/\{frameClass}/g, frameClass)
  116 + .replace(/\{fileindex}/g, ind)
  117 + .replace(/\{content}/g, data.content[i])
  118 + .replace(/\{footer}/g, previewCache.footer(id, i, isDisabled));
  119 + if (data.tags.length && data.tags[i]) {
  120 + out = replaceTags(out, data.tags[i]);
  121 + }
  122 + if (!isEmpty(config) && !isEmpty(config.frameAttr)) {
  123 + $tmp = $(document.createElement('div')).html(out);
  124 + $tmp.find('.file-preview-initial').attr(config.frameAttr);
  125 + out = $tmp.html();
  126 + $tmp.remove();
  127 + }
  128 + return out;
  129 + },
  130 + add: function (id, content, config, tags, append) {
  131 + var data = $.extend(true, {}, previewCache.data[id]), index;
  132 + if (!isArray(content)) {
  133 + content = content.split(data.delimiter);
  134 + }
  135 + if (append) {
  136 + index = data.content.push(content) - 1;
  137 + data.config[index] = config;
  138 + data.tags[index] = tags;
  139 + } else {
  140 + index = content.length;
  141 + data.content = content;
  142 + data.config = config;
  143 + data.tags = tags;
  144 + }
  145 + previewCache.data[id] = data;
  146 + return index;
  147 + },
  148 + set: function (id, content, config, tags, append) {
  149 + var data = $.extend(true, {}, previewCache.data[id]), i, chk;
  150 + if (!content || !content.length) {
  151 + return;
  152 + }
  153 + if (!isArray(content)) {
  154 + content = content.split(data.delimiter);
  155 + }
  156 + chk = content.filter(function (n) {
  157 + return n !== null;
  158 + });
  159 + if (!chk.length) {
  160 + return;
  161 + }
  162 + if (data.content === undefined) {
  163 + data.content = [];
  164 + }
  165 + if (data.config === undefined) {
  166 + data.config = [];
  167 + }
  168 + if (data.tags === undefined) {
  169 + data.tags = [];
  170 + }
  171 + if (append) {
  172 + for (i = 0; i < content.length; i++) {
  173 + if (content[i]) {
  174 + data.content.push(content[i]);
  175 + }
  176 + }
  177 + for (i = 0; i < config.length; i++) {
  178 + if (config[i]) {
  179 + data.config.push(config[i]);
  180 + }
  181 + }
  182 + for (i = 0; i < tags.length; i++) {
  183 + if (tags[i]) {
  184 + data.tags.push(tags[i]);
  185 + }
  186 + }
  187 + } else {
  188 + data.content = content;
  189 + data.config = config;
  190 + data.tags = tags;
  191 + }
  192 + previewCache.data[id] = data;
  193 + },
  194 + unset: function (id, index) {
  195 + var chk = previewCache.count(id);
  196 + if (!chk) {
  197 + return;
  198 + }
  199 + if (chk === 1) {
  200 + previewCache.data[id].content = [];
  201 + previewCache.data[id].config = [];
  202 + return;
  203 + }
  204 + previewCache.data[id].content[index] = null;
  205 + previewCache.data[id].config[index] = null;
  206 + },
  207 + out: function (id) {
  208 + var html = '', data = previewCache.data[id], caption, len = previewCache.count(id, true);
  209 + if (len === 0) {
  210 + return {content: '', caption: ''};
  211 + }
  212 + for (var i = 0; i < len; i++) {
  213 + html += previewCache.get(id, i);
  214 + }
  215 + caption = data.msg(previewCache.count(id));
  216 + return {content: html, caption: caption};
  217 + },
  218 + footer: function (id, i, isDisabled) {
  219 + var data = previewCache.data[id];
  220 + isDisabled = isDisabled === undefined ? true : isDisabled;
  221 + if (data.config.length === 0 || isEmpty(data.config[i])) {
  222 + return '';
  223 + }
  224 + var config = data.config[i],
  225 + caption = isSet('caption', config) ? config.caption : '',
  226 + width = isSet('width', config) ? config.width : 'auto',
  227 + url = isSet('url', config) ? config.url : false,
  228 + key = isSet('key', config) ? config.key : null,
  229 + disabled = (url === false) && isDisabled,
  230 + actions = data.isDelete ? data.actions(false, true, disabled, url, key) : '',
  231 + footer = data.footer.replace(/\{actions}/g, actions);
  232 + return footer.replace(/\{caption}/g, caption)
  233 + .replace(/\{width}/g, width)
  234 + .replace(/\{indicator}/g, '')
  235 + .replace(/\{indicatorTitle}/g, '');
  236 + }
  237 + };
  238 + getNum = function (num, def) {
  239 + def = def || 0;
  240 + if (typeof num === "number") {
  241 + return num;
  242 + }
  243 + if (typeof num === "string") {
  244 + num = parseFloat(num);
  245 + }
  246 + return isNaN(num) ? def : num;
  247 + };
  248 + hasFileAPISupport = function () {
  249 + return window.File && window.FileReader;
  250 + };
  251 + hasDragDropSupport = function () {
  252 + var div = document.createElement('div');
  253 + /** @namespace div.draggable */
  254 + /** @namespace div.ondragstart */
  255 + /** @namespace div.ondrop */
  256 + return !isIE(9) && !isEdge() && // Fix for MS Edge drag & drop support bug
  257 + (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
  258 + };
  259 + hasFileUploadSupport = function () {
  260 + return hasFileAPISupport() && window.FormData;
  261 + };
  262 + addCss = function ($el, css) {
  263 + $el.removeClass(css).addClass(css);
  264 + };
  265 + STYLE_SETTING = 'style="width:{width};height:{height};"';
  266 + OBJECT_PARAMS = ' <param name="controller" value="true" />\n' +
  267 + ' <param name="allowFullScreen" value="true" />\n' +
  268 + ' <param name="allowScriptAccess" value="always" />\n' +
  269 + ' <param name="autoPlay" value="false" />\n' +
  270 + ' <param name="autoStart" value="false" />\n' +
  271 + ' <param name="quality" value="high" />\n';
  272 + DEFAULT_PREVIEW = '<div class="file-preview-other">\n' +
  273 + ' <span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
  274 + '</div>';
  275 + defaultFileActionSettings = {
  276 + removeIcon: '<i class="glyphicon glyphicon-trash text-danger"></i>',
  277 + removeClass: 'btn btn-xs btn-default',
  278 + removeTitle: 'Remove file',
  279 + uploadIcon: '<i class="glyphicon glyphicon-upload text-info"></i>',
  280 + uploadClass: 'btn btn-xs btn-default',
  281 + uploadTitle: 'Upload file',
  282 + indicatorNew: '<i class="glyphicon glyphicon-hand-down text-warning"></i>',
  283 + indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
  284 + indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
  285 + indicatorLoading: '<i class="glyphicon glyphicon-hand-up text-muted"></i>',
  286 + indicatorNewTitle: 'Not uploaded yet',
  287 + indicatorSuccessTitle: 'Uploaded',
  288 + indicatorErrorTitle: 'Upload Error',
  289 + indicatorLoadingTitle: 'Uploading ...'
  290 + };
  291 + tMain1 = '{preview}\n' +
  292 + '<div class="kv-upload-progress hide"></div>\n' +
  293 + '<div class="input-group {class}">\n' +
  294 + ' {caption}\n' +
  295 + ' <div class="input-group-btn">\n' +
  296 + ' {remove}\n' +
  297 + ' {cancel}\n' +
  298 + ' {upload}\n' +
  299 + ' {browse}\n' +
  300 + ' </div>\n' +
  301 + '</div>';
  302 + tMain2 = '{preview}\n<div class="kv-upload-progress hide"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n';
  303 + tPreview = '<div class="file-preview {class}">\n' +
  304 + ' {close}' +
  305 + ' <div class="{dropClass}">\n' +
  306 + ' <div class="file-preview-thumbnails">\n' +
  307 + ' </div>\n' +
  308 + ' <div class="clearfix"></div>' +
  309 + ' <div class="file-preview-status text-center text-success"></div>\n' +
  310 + ' <div class="kv-fileinput-error"></div>\n' +
  311 + ' </div>\n' +
  312 + '</div>';
  313 + tClose = '<div class="close fileinput-remove">&times;</div>\n';
  314 + tIcon = '<span class="glyphicon glyphicon-file kv-caption-icon"></span>';
  315 + tCaption = '<div tabindex="500" class="form-control file-caption {class}">\n' +
  316 + ' <div class="file-caption-name"></div>\n' +
  317 + '</div>\n';
  318 + //noinspection HtmlUnknownAttribute
  319 + tBtnDefault = '<button type="{type}" tabindex="500" title="{title}" class="{css}" {status}>{icon}{label}</button>';
  320 + tBtnLink = '<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon}{label}</a>';
  321 + tBtnBrowse = '<div tabindex="500" class="{css}" {status}>{icon}{label}</div>';
  322 + tModal = '<div id="{id}" class="file-preview-detail-modal modal fade" tabindex="-1">\n' +
  323 + ' <div class="modal-dialog modal-lg">\n' +
  324 + ' <div class="modal-content">\n' +
  325 + ' <div class="modal-header">\n' +
  326 + ' <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>\n' +
  327 + ' <h3 class="modal-title">{heading} <small>{title}</small></h3>\n' +
  328 + ' </div>\n' +
  329 + ' <div class="modal-body">\n' +
  330 + ' <pre>{body}</pre>\n' +
  331 + ' </div>\n' +
  332 + ' </div>\n' +
  333 + ' </div>\n' +
  334 + '</div>';
  335 + tProgress = '<div class="progress">\n' +
  336 + ' <div class="{class}" role="progressbar"' +
  337 + ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
  338 + ' {percent}%\n' +
  339 + ' </div>\n' +
  340 + '</div>';
  341 + tFooter = '<div class="file-thumbnail-footer">\n' +
  342 + ' <div class="file-footer-caption" title="{caption}">{caption}</div>\n' +
  343 + ' {progress} {actions}\n' +
  344 + '</div>';
  345 + tActions = '<div class="file-actions">\n' +
  346 + ' <div class="file-footer-buttons">\n' +
  347 + ' {upload}{delete}{other}' +
  348 + ' </div>\n' +
  349 + ' <div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>\n' +
  350 + ' <div class="clearfix"></div>\n' +
  351 + '</div>';
  352 + tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
  353 + 'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
  354 + tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
  355 + ' {uploadIcon}\n</button>\n';
  356 + tZoom = '<button type="button" class="btn btn-default btn-xs btn-block" title="{zoomTitle}: {caption}" onclick="{dialog}">\n' +
  357 + ' {zoomInd}\n' +
  358 + '</button>\n';
  359 + tGeneric = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n' +
  360 + ' {content}\n' +
  361 + ' {footer}\n' +
  362 + '</div>\n';
  363 + tHtml = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n' +
  364 + ' <object class="file-object" data="{data}" type="{type}" width="{width}" height="{height}">\n' +
  365 + ' ' + DEFAULT_PREVIEW + '\n' +
  366 + ' </object>\n' +
  367 + ' {footer}\n' +
  368 + '</div>';
  369 + tImage = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n' +
  370 + ' <img src="{data}" class="file-preview-image" title="{caption}" alt="{caption}" ' + STYLE_SETTING + '>\n' +
  371 + ' {footer}\n' +
  372 + '</div>\n';
  373 + tText = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n' +
  374 + ' <pre class="file-preview-text" title="{caption}" ' + STYLE_SETTING + '>{data}</pre>\n' +
  375 + ' {zoom}\n' +
  376 + ' {footer}\n' +
  377 + '</div>';
  378 + tVideo = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  379 + ' title="{caption}" ' + STYLE_SETTING + '>\n' +
  380 + ' <video width="{width}" height="{height}" controls>\n' +
  381 + ' <source src="{data}" type="{type}">\n' +
  382 + ' ' + DEFAULT_PREVIEW + '\n' +
  383 + ' </video>\n' +
  384 + ' {footer}\n' +
  385 + '</div>\n';
  386 + tAudio = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  387 + ' title="{caption}" ' + STYLE_SETTING + '>\n' +
  388 + ' <audio controls>\n' +
  389 + ' <source src="' + '{data}' + '" type="{type}">\n' +
  390 + ' ' + DEFAULT_PREVIEW + '\n' +
  391 + ' </audio>\n' +
  392 + ' {footer}\n' +
  393 + '</div>';
  394 + tFlash = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  395 + ' title="{caption}" ' + STYLE_SETTING + '>\n' +
  396 + ' <object class="file-object" type="application/x-shockwave-flash" width="{width}" height="{height}" data="{data}">\n' +
  397 + OBJECT_PARAMS + ' ' + DEFAULT_PREVIEW + '\n' +
  398 + ' </object>\n' +
  399 + ' {footer}\n' +
  400 + '</div>\n';
  401 + tObject = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  402 + ' title="{caption}" ' + STYLE_SETTING + '>\n' +
  403 + ' <object class="file-object" data="{data}" type="{type}" width="{width}" height="{height}">\n' +
  404 + ' <param name="movie" value="{caption}" />\n' +
  405 + OBJECT_PARAMS + ' ' + DEFAULT_PREVIEW + '\n' +
  406 + ' </object>\n' +
  407 + ' {footer}\n' +
  408 + '</div>';
  409 + tOther = '<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  410 + ' title="{caption}" ' + STYLE_SETTING + '>\n' +
  411 + ' <div class="file-preview-other-frame">\n' +
  412 + ' ' + DEFAULT_PREVIEW + '\n' +
  413 + ' </div>\n' +
  414 + ' <div class="file-preview-other-footer">{footer}</div>\n' +
  415 + '</div>';
  416 + defaultLayoutTemplates = {
  417 + main1: tMain1,
  418 + main2: tMain2,
  419 + preview: tPreview,
  420 + close: tClose,
  421 + zoom: tZoom,
  422 + icon: tIcon,
  423 + caption: tCaption,
  424 + modal: tModal,
  425 + progress: tProgress,
  426 + footer: tFooter,
  427 + actions: tActions,
  428 + actionDelete: tActionDelete,
  429 + actionUpload: tActionUpload,
  430 + btnDefault: tBtnDefault,
  431 + btnLink: tBtnLink,
  432 + btnBrowse: tBtnBrowse
  433 + };
  434 + defaultPreviewTemplates = {
  435 + generic: tGeneric,
  436 + html: tHtml,
  437 + image: tImage,
  438 + text: tText,
  439 + video: tVideo,
  440 + audio: tAudio,
  441 + flash: tFlash,
  442 + object: tObject,
  443 + other: tOther
  444 + };
  445 + defaultPreviewTypes = ['image', 'html', 'text', 'video', 'audio', 'flash', 'object'];
  446 + defaultPreviewSettings = {
  447 + image: {width: "auto", height: "160px"},
  448 + html: {width: "213px", height: "160px"},
  449 + text: {width: "160px", height: "136px"},
  450 + video: {width: "213px", height: "160px"},
  451 + audio: {width: "213px", height: "80px"},
  452 + flash: {width: "213px", height: "160px"},
  453 + object: {width: "160px", height: "160px"},
  454 + other: {width: "160px", height: "160px"}
  455 + };
  456 + defaultFileTypeSettings = {
  457 + image: function (vType, vName) {
  458 + return (vType !== undefined) ? vType.match('image.*') : vName.match(/\.(gif|png|jpe?g)$/i);
  459 + },
  460 + html: function (vType, vName) {
  461 + return (vType !== undefined) ? vType === 'text/html' : vName.match(/\.(htm|html)$/i);
  462 + },
  463 + text: function (vType, vName) {
  464 + return (vType !== undefined && vType.match('text.*')) || vName.match(
  465 + /\.(txt|md|csv|nfo|ini|json|php|js|css)$/i);
  466 + },
  467 + video: function (vType, vName) {
  468 + return (vType !== undefined && vType.match(/\.video\/(ogg|mp4|webm|3gp)$/i)) || vName.match(
  469 + /\.(og?|mp4|webm|3gp)$/i);
  470 + },
  471 + audio: function (vType, vName) {
  472 + return (vType !== undefined && vType.match(/\.audio\/(ogg|mp3|wav)$/i)) || vName.match(/\.(ogg|mp3|wav)$/i);
  473 + },
  474 + flash: function (vType, vName) {
  475 + return (vType !== undefined && vType === 'application/x-shockwave-flash') || vName.match(/\.(swf)$/i);
  476 + },
  477 + object: function () {
  478 + return true;
  479 + },
  480 + other: function () {
  481 + return true;
  482 + }
  483 + };
  484 + isEmpty = function (value, trim) {
  485 + return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
  486 + };
  487 + isArray = function (a) {
  488 + return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
  489 + };
  490 + isSet = function (needle, haystack) {
  491 + return (typeof haystack === 'object' && needle in haystack);
  492 + };
  493 + getElement = function (options, param, value) {
  494 + return (isEmpty(options) || isEmpty(options[param])) ? value : $(options[param]);
  495 + };
  496 + uniqId = function () {
  497 + return Math.round(new Date().getTime() + (Math.random() * 100));
  498 + };
  499 + htmlEncode = function (str) {
  500 + return str.replace(/&/g, '&amp;')
  501 + .replace(/</g, '&lt;')
  502 + .replace(/>/g, '&gt;')
  503 + .replace(/"/g, '&quot;')
  504 + .replace(/'/g, '&apos;');
  505 + };
  506 + replaceTags = function (str, tags) {
  507 + var out = str;
  508 + if (!tags) {
  509 + return out;
  510 + }
  511 + $.each(tags, function (key, value) {
  512 + if (typeof value === "function") {
  513 + value = value();
  514 + }
  515 + out = out.split(key).join(value);
  516 + });
  517 + return out;
  518 + };
  519 + //noinspection JSUnresolvedVariable
  520 + objUrl = window.URL || window.webkitURL;
  521 + FileInput = function (element, options) {
  522 + var self = this;
  523 + self.$element = $(element);
  524 + if (!self.validate()) {
  525 + return;
  526 + }
  527 + self.isPreviewable = hasFileAPISupport();
  528 + self.isIE9 = isIE(9);
  529 + self.isIE10 = isIE(10);
  530 + if (self.isPreviewable || self.isIE9) {
  531 + self.init(options);
  532 + self.listen();
  533 + } else {
  534 + self.$element.removeClass('file-loading');
  535 + }
  536 + };
  537 +
  538 + FileInput.prototype = {
  539 + constructor: FileInput,
  540 + validate: function () {
  541 + var self = this, $exception;
  542 + if (self.$element.attr('type') === 'file') {
  543 + return true;
  544 + }
  545 + $exception = '<div class="help-block alert alert-warning">' +
  546 + '<h4>Invalid Input Type</h4>' +
  547 + 'You must set an input <code>type = file</code> for <b>bootstrap-fileinput</b> plugin to initialize.' +
  548 + '</div>';
  549 + self.$element.after($exception);
  550 + return false;
  551 + },
  552 + init: function (options) {
  553 + var self = this, $el = self.$element, t;
  554 + $.each(options, function (key, value) {
  555 + switch (key) {
  556 + case 'minFileCount':
  557 + case 'maxFileCount':
  558 + case 'maxFileSize':
  559 + self[key] = getNum(value);
  560 + break;
  561 + default:
  562 + self[key] = value;
  563 + break;
  564 + }
  565 + });
  566 + self.fileInputCleared = false;
  567 + self.fileBatchCompleted = true;
  568 + if (!self.isPreviewable) {
  569 + self.showPreview = false;
  570 + }
  571 + self.uploadFileAttr = !isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
  572 + self.reader = null;
  573 + self.formdata = {};
  574 + self.clearStack();
  575 + self.uploadCount = 0;
  576 + self.uploadStatus = {};
  577 + self.uploadLog = [];
  578 + self.uploadAsyncCount = 0;
  579 + self.loadedImages = [];
  580 + self.totalImagesCount = 0;
  581 + self.ajaxRequests = [];
  582 + self.isError = false;
  583 + self.ajaxAborted = false;
  584 + self.cancelling = false;
  585 + t = self.getLayoutTemplate('progress');
  586 + self.progressTemplate = t.replace('{class}', self.progressClass);
  587 + self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
  588 + self.dropZoneEnabled = hasDragDropSupport() && self.dropZoneEnabled;
  589 + self.isDisabled = self.$element.attr('disabled') || self.$element.attr('readonly');
  590 + self.isUploadable = hasFileUploadSupport() && !isEmpty(self.uploadUrl);
  591 + self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self.slugDefault;
  592 + self.mainTemplate = self.showCaption ? self.getLayoutTemplate('main1') : self.getLayoutTemplate('main2');
  593 + self.captionTemplate = self.getLayoutTemplate('caption');
  594 + self.previewGenericTemplate = self.getPreviewTemplate('generic');
  595 + if (self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
  596 + self.imageCanvas = document.createElement('canvas');
  597 + self.imageCanvasContext = self.imageCanvas.getContext('2d');
  598 + }
  599 + if (isEmpty(self.$element.attr('id'))) {
  600 + self.$element.attr('id', uniqId());
  601 + }
  602 + if (self.$container === undefined) {
  603 + self.$container = self.createContainer();
  604 + } else {
  605 + self.refreshContainer();
  606 + }
  607 + self.$progress = self.$container.find('.kv-upload-progress');
  608 + self.$btnUpload = self.$container.find('.fileinput-upload');
  609 + self.$captionContainer = getElement(options, 'elCaptionContainer', self.$container.find('.file-caption'));
  610 + self.$caption = getElement(options, 'elCaptionText', self.$container.find('.file-caption-name'));
  611 + self.$previewContainer = getElement(options, 'elPreviewContainer', self.$container.find('.file-preview'));
  612 + self.$preview = getElement(options, 'elPreviewImage', self.$container.find('.file-preview-thumbnails'));
  613 + self.$previewStatus = getElement(options, 'elPreviewStatus', self.$container.find('.file-preview-status'));
  614 + self.$errorContainer = getElement(options, 'elErrorContainer',
  615 + self.$previewContainer.find('.kv-fileinput-error'));
  616 + if (!isEmpty(self.msgErrorClass)) {
  617 + addCss(self.$errorContainer, self.msgErrorClass);
  618 + }
  619 + self.$errorContainer.hide();
  620 + self.fileActionSettings = $.extend(defaultFileActionSettings, options.fileActionSettings);
  621 + self.previewInitId = "preview-" + uniqId();
  622 + self.id = self.$element.attr('id');
  623 + previewCache.init(self);
  624 + self.initPreview(true);
  625 + self.initPreviewDeletes();
  626 + self.options = options;
  627 + self.setFileDropZoneTitle();
  628 + self.$element.removeClass('file-loading');
  629 + if (self.$element.attr('disabled')) {
  630 + self.disable();
  631 + }
  632 + },
  633 + parseError: function (jqXHR, errorThrown, fileName) {
  634 + var self = this, errMsg = $.trim(errorThrown + ''),
  635 + dot = errMsg.slice(-1) === '.' ? '' : '.',
  636 + text = jqXHR.responseJSON !== undefined && jqXHR.responseJSON.error !== undefined ?
  637 + jqXHR.responseJSON.error : jqXHR.responseText;
  638 + if (self.cancelling && self.msgUploadAborted) {
  639 + errMsg = self.msgUploadAborted;
  640 + }
  641 + if (self.showAjaxErrorDetails && text) {
  642 + text = $.trim(text.replace(/\n\s*\n/g, '\n'));
  643 + text = text.length > 0 ? '<pre>' + text + '</pre>' : '';
  644 + errMsg += dot + text;
  645 + } else {
  646 + errMsg += dot;
  647 + }
  648 + self.cancelling = false;
  649 + return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
  650 + },
  651 + raise: function (event, params) {
  652 + var self = this, e = $.Event(event);
  653 + if (params !== undefined) {
  654 + self.$element.trigger(e, params);
  655 + } else {
  656 + self.$element.trigger(e);
  657 + }
  658 + if (e.isDefaultPrevented()) {
  659 + return false;
  660 + }
  661 + if (!e.result) {
  662 + return e.result;
  663 + }
  664 + switch (event) {
  665 + // ignore these events
  666 + case 'filebatchuploadcomplete':
  667 + case 'filebatchuploadsuccess':
  668 + case 'fileuploaded':
  669 + case 'fileclear':
  670 + case 'filecleared':
  671 + case 'filereset':
  672 + case 'fileerror':
  673 + case 'filefoldererror':
  674 + case 'fileuploaderror':
  675 + case 'filebatchuploaderror':
  676 + case 'filedeleteerror':
  677 + case 'filecustomerror':
  678 + case 'filesuccessremove':
  679 + break;
  680 + // receive data response via `filecustomerror` event`
  681 + default:
  682 + self.ajaxAborted = e.result;
  683 + break;
  684 + }
  685 + return true;
  686 + },
  687 + getLayoutTemplate: function (t) {
  688 + var self = this,
  689 + template = isSet(t, self.layoutTemplates) ? self.layoutTemplates[t] : defaultLayoutTemplates[t];
  690 + if (isEmpty(self.customLayoutTags)) {
  691 + return template;
  692 + }
  693 + return replaceTags(template, self.customLayoutTags);
  694 + },
  695 + getPreviewTemplate: function (t) {
  696 + var self = this,
  697 + template = isSet(t, self.previewTemplates) ? self.previewTemplates[t] : defaultPreviewTemplates[t];
  698 + if (isEmpty(self.customPreviewTags)) {
  699 + return template;
  700 + }
  701 + return replaceTags(template, self.customPreviewTags);
  702 + },
  703 + parseFilePreviewIcon: function (content, fname) {
  704 + var self = this, ext, icn = self.previewFileIcon;
  705 + if (fname && fname.indexOf('.') > -1) {
  706 + ext = fname.split('.').pop();
  707 + if (self.previewFileIconSettings && self.previewFileIconSettings[ext]) {
  708 + icn = self.previewFileIconSettings[ext];
  709 + }
  710 + if (self.previewFileExtSettings) {
  711 + $.each(self.previewFileExtSettings, function (key, func) {
  712 + if (self.previewFileIconSettings[key] && func(ext)) {
  713 + icn = self.previewFileIconSettings[key];
  714 + }
  715 + });
  716 + }
  717 + }
  718 + if (content.indexOf('{previewFileIcon}') > -1) {
  719 + return content.replace(/\{previewFileIconClass}/g, self.previewFileIconClass).replace(
  720 + /\{previewFileIcon}/g, icn);
  721 + }
  722 + return content;
  723 + },
  724 + getOutData: function (jqXHR, responseData, filesData) {
  725 + var self = this;
  726 + jqXHR = jqXHR || {};
  727 + responseData = responseData || {};
  728 + filesData = filesData || self.filestack.slice(0) || {};
  729 + return {
  730 + form: self.formdata,
  731 + files: filesData,
  732 + filenames: self.filenames,
  733 + extra: self.getExtraData(),
  734 + response: responseData,
  735 + reader: self.reader,
  736 + jqXHR: jqXHR
  737 + };
  738 + },
  739 + listen: function () {
  740 + var self = this, $el = self.$element, $cap = self.$captionContainer, $btnFile = self.$btnFile,
  741 + $form = $el.closest('form'), $cont = self.$container;
  742 + handler($el, 'change', $.proxy(self.change, self));
  743 + handler($btnFile, 'click', function () {
  744 + self.raise('filebrowse');
  745 + if (self.isError && !self.isUploadable) {
  746 + self.clear();
  747 + }
  748 + $cap.focus();
  749 + });
  750 + handler($form, 'reset', $.proxy(self.reset, self));
  751 + handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
  752 + handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
  753 + if (self.isUploadable && self.dropZoneEnabled && self.showPreview) {
  754 + self.initDragDrop();
  755 + }
  756 + if (!self.isUploadable) {
  757 + handler($form, 'submit', $.proxy(self.submitForm, self));
  758 + }
  759 + handler(self.$container.find('.fileinput-upload'), 'click', function (e) {
  760 + var $btn = $(this), $form, isEnabled = !$btn.hasClass('disabled') && isEmpty($btn.attr('disabled'));
  761 + if (!self.isUploadable) {
  762 + if (isEnabled && $btn.attr('type') !== 'submit') {
  763 + $form = $btn.closest('form');
  764 + // downgrade to normal form submit if possible
  765 + if ($form.length) {
  766 + $form.trigger('submit');
  767 + }
  768 + e.preventDefault();
  769 + }
  770 + return;
  771 + }
  772 + e.preventDefault();
  773 + if (isEnabled) {
  774 + self.upload();
  775 + }
  776 + });
  777 + },
  778 + submitForm: function () {
  779 + var self = this, $el = self.$element, files = $el.get(0).files;
  780 + if (files && self.minFileCount > 0 && self.getFileCount(files.length) < self.minFileCount) {
  781 + self.noFilesError({});
  782 + return false;
  783 + }
  784 + return !self.abort({});
  785 + },
  786 + abort: function (params) {
  787 + var self = this, data;
  788 + if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
  789 + data = $.extend(self.getOutData(), params);
  790 + data.abortData = self.ajaxAborted.data || {};
  791 + data.abortMessage = self.ajaxAborted.message;
  792 + self.cancel();
  793 + self.setProgress(100);
  794 + self.showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
  795 + return true;
  796 + }
  797 + return false;
  798 + },
  799 + noFilesError: function (params) {
  800 + var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
  801 + msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
  802 + $error = self.$errorContainer;
  803 + self.addError(msg);
  804 + self.isError = true;
  805 + self.updateFileDetails(0);
  806 + $error.fadeIn(800);
  807 + self.raise('fileerror', [params]);
  808 + self.clearFileInput();
  809 + addCss(self.$container, 'has-error');
  810 + },
  811 + setProgress: function (p, $el) {
  812 + var self = this, pct = Math.min(p, 100),
  813 + template = pct < 100 ? self.progressTemplate : self.progressCompleteTemplate;
  814 + $el = $el || self.$progress;
  815 + if (!isEmpty(template)) {
  816 + $el.html(template.replace(/\{percent}/g, pct));
  817 + }
  818 + },
  819 + lock: function () {
  820 + var self = this;
  821 + self.resetErrors();
  822 + self.disable();
  823 + if (self.showRemove) {
  824 + addCss(self.$container.find('.fileinput-remove'), 'hide');
  825 + }
  826 + if (self.showCancel) {
  827 + self.$container.find('.fileinput-cancel').removeClass('hide');
  828 + }
  829 + self.raise('filelock', [self.filestack, self.getExtraData()]);
  830 + },
  831 + unlock: function (reset) {
  832 + var self = this;
  833 + if (reset === undefined) {
  834 + reset = true;
  835 + }
  836 + self.enable();
  837 + if (self.showCancel) {
  838 + addCss(self.$container.find('.fileinput-cancel'), 'hide');
  839 + }
  840 + if (self.showRemove) {
  841 + self.$container.find('.fileinput-remove').removeClass('hide');
  842 + }
  843 + if (reset) {
  844 + self.resetFileStack();
  845 + }
  846 + self.raise('fileunlock', [self.filestack, self.getExtraData()]);
  847 + },
  848 + resetFileStack: function () {
  849 + var self = this, i = 0, newstack = [], newnames = [];
  850 + self.getThumbs().each(function () {
  851 + var $thumb = $(this), ind = $thumb.attr('data-fileindex'),
  852 + file = self.filestack[ind];
  853 + if (ind === -1) {
  854 + return;
  855 + }
  856 + if (file !== undefined) {
  857 + newstack[i] = file;
  858 + newnames[i] = self.getFileName(file);
  859 + $thumb.attr({
  860 + 'id': self.previewInitId + '-' + i,
  861 + 'data-fileindex': i
  862 + });
  863 + i++;
  864 + } else {
  865 + $thumb.attr({
  866 + 'id': 'uploaded-' + uniqId(),
  867 + 'data-fileindex': '-1'
  868 + });
  869 + }
  870 + });
  871 + self.filestack = newstack;
  872 + self.filenames = newnames;
  873 + },
  874 + destroy: function () {
  875 + var self = this, $cont = self.$container;
  876 + $cont.find('.file-drop-zone').off();
  877 + self.$element.insertBefore($cont).off('.fileinput').removeData();
  878 + $cont.off().remove();
  879 + },
  880 + refresh: function (options) {
  881 + var self = this, $el = self.$element;
  882 + options = options ? $.extend(self.options, options) : self.options;
  883 + self.destroy();
  884 + $el.fileinput(options);
  885 + if ($el.val()) {
  886 + $el.trigger('change.fileinput');
  887 + }
  888 + },
  889 + initDragDrop: function () {
  890 + var self = this, $zone = self.$container.find('.file-drop-zone'),
  891 + allEvents = 'dragenter.fileinput dragover.fileinput drop.fileinput';
  892 + handler($zone, 'dragenter.fileinput dragover.fileinput', function (e) {
  893 + var hasFiles = $.inArray('Files', e.originalEvent.dataTransfer.types) > -1;
  894 + e.stopPropagation();
  895 + e.preventDefault();
  896 + if (self.isDisabled || !hasFiles) {
  897 + e.originalEvent.dataTransfer.effectAllowed = 'none';
  898 + e.originalEvent.dataTransfer.dropEffect = 'none';
  899 + return;
  900 + }
  901 + addCss($(this), 'file-highlighted');
  902 + }, true);
  903 + handler($zone, 'dragleave', function (e) {
  904 + e.stopPropagation();
  905 + e.preventDefault();
  906 + if (self.isDisabled) {
  907 + return;
  908 + }
  909 + $(this).removeClass('file-highlighted');
  910 + });
  911 + handler($zone, 'drop', function (e) {
  912 + e.preventDefault();
  913 + /** @namespace e.originalEvent.dataTransfer */
  914 + if (self.isDisabled || isEmpty(e.originalEvent.dataTransfer.files)) {
  915 + return;
  916 + }
  917 + self.change(e, 'dragdrop');
  918 + $(this).removeClass('file-highlighted');
  919 + });
  920 + handler($(document), allEvents, function (e) {
  921 + e.stopPropagation();
  922 + e.preventDefault();
  923 + }, true);
  924 + },
  925 + setFileDropZoneTitle: function () {
  926 + var self = this, $zone = self.$container.find('.file-drop-zone');
  927 + $zone.find('.' + self.dropZoneTitleClass).remove();
  928 + if (!self.isUploadable || !self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
  929 + return;
  930 + }
  931 + if ($zone.find('.file-preview-frame').length === 0 && isEmpty(self.defaultPreviewContent)) {
  932 + $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + self.dropZoneTitle + '</div>');
  933 + }
  934 + self.$container.removeClass('file-input-new');
  935 + addCss(self.$container, 'file-input-ajax-new');
  936 + },
  937 + errorsExist: function () {
  938 + var self = this, $err;
  939 + if (self.$errorContainer.find('li').length) {
  940 + return true;
  941 + }
  942 + $err = $(document.createElement('div')).html(self.$errorContainer.html());
  943 + $err.find('span.kv-error-close').remove();
  944 + $err.find('ul').remove();
  945 + return $.trim($err.text()).length ? true : false;
  946 + },
  947 + getMsgSelected: function (n) {
  948 + var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
  949 + return self.msgSelected.replace('{n}', n).replace('{files}', strFiles);
  950 + },
  951 + renderThumbProgress: function () {
  952 + return '<div class="file-thumb-progress hide">' + this.progressTemplate.replace(/\{percent}/g,
  953 + '0') + '</div>';
  954 + },
  955 + renderFileFooter: function (caption, width) {
  956 + var self = this, config = self.fileActionSettings, footer, out, template = self.getLayoutTemplate('footer');
  957 + if (self.isUploadable) {
  958 + footer = template.replace(/\{actions}/g, self.renderFileActions(true, true, false, false, false));
  959 + out = footer.replace(/\{caption}/g, caption)
  960 + .replace(/\{width}/g, width)
  961 + .replace(/\{progress}/g, self.renderThumbProgress())
  962 + .replace(/\{indicator}/g, config.indicatorNew)
  963 + .replace(/\{indicatorTitle}/g, config.indicatorNewTitle);
  964 + } else {
  965 + out = template.replace(/\{actions}/g, '')
  966 + .replace(/\{caption}/g, caption)
  967 + .replace(/\{progress}/g, '')
  968 + .replace(/\{width}/g, width)
  969 + .replace(/\{indicator}/g, '')
  970 + .replace(/\{indicatorTitle}/g, '');
  971 + }
  972 + out = replaceTags(out, self.previewThumbTags);
  973 + return out;
  974 + },
  975 + renderFileActions: function (showUpload, showDelete, disabled, url, key) {
  976 + if (!showUpload && !showDelete) {
  977 + return '';
  978 + }
  979 + var self = this,
  980 + vUrl = url === false ? '' : ' data-url="' + url + '"',
  981 + vKey = key === false ? '' : ' data-key="' + key + '"',
  982 + btnDelete = self.getLayoutTemplate('actionDelete'),
  983 + btnUpload = '',
  984 + template = self.getLayoutTemplate('actions'),
  985 + otherButtons = self.otherActionButtons.replace(/\{dataKey}/g, vKey),
  986 + config = self.fileActionSettings,
  987 + removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
  988 + btnDelete = btnDelete
  989 + .replace(/\{removeClass}/g, removeClass)
  990 + .replace(/\{removeIcon}/g, config.removeIcon)
  991 + .replace(/\{removeTitle}/g, config.removeTitle)
  992 + .replace(/\{dataUrl}/g, vUrl)
  993 + .replace(/\{dataKey}/g, vKey);
  994 + if (showUpload) {
  995 + btnUpload = self.getLayoutTemplate('actionUpload')
  996 + .replace(/\{uploadClass}/g, config.uploadClass)
  997 + .replace(/\{uploadIcon}/g, config.uploadIcon)
  998 + .replace(/\{uploadTitle}/g, config.uploadTitle);
  999 + }
  1000 + return template
  1001 + .replace(/\{delete}/g, btnDelete)
  1002 + .replace(/\{upload}/g, btnUpload)
  1003 + .replace(/\{other}/g, otherButtons);
  1004 + },
  1005 + setThumbStatus: function ($thumb, status) {
  1006 + var self = this;
  1007 + if (!self.showPreview) {
  1008 + return;
  1009 + }
  1010 + var icon = 'indicator' + status, msg = icon + 'Title',
  1011 + css = 'file-preview-' + status.toLowerCase(),
  1012 + $indicator = $thumb.find('.file-upload-indicator'),
  1013 + config = self.fileActionSettings;
  1014 + $thumb.removeClass('file-preview-success file-preview-error file-preview-loading');
  1015 + if (status === 'Error') {
  1016 + $thumb.find('.kv-file-upload').attr('disabled', true);
  1017 + }
  1018 + $indicator.html(config[icon]);
  1019 + $indicator.attr('title', config[msg]);
  1020 + $thumb.addClass(css);
  1021 + },
  1022 + clearPreview: function () {
  1023 + var self = this, $thumbs = !self.showUploadedThumbs ? self.$preview.find('.file-preview-frame') :
  1024 + self.$preview.find('.file-preview-frame:not(.file-preview-success)');
  1025 + $thumbs.remove();
  1026 + if (!self.$preview.find('.file-preview-frame').length || !self.showPreview) {
  1027 + self.resetUpload();
  1028 + }
  1029 + self.validateDefaultPreview();
  1030 + },
  1031 + initPreview: function (isInit) {
  1032 + var self = this, cap = self.initialCaption || '', out;
  1033 + if (!previewCache.count(self.id)) {
  1034 + self.clearPreview();
  1035 + if (isInit) {
  1036 + self.setCaption(cap);
  1037 + } else {
  1038 + self.initCaption();
  1039 + }
  1040 + return;
  1041 + }
  1042 + out = previewCache.out(self.id);
  1043 + cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
  1044 + self.$preview.html(out.content);
  1045 + self.setCaption(cap);
  1046 + if (!isEmpty(out.content)) {
  1047 + self.$container.removeClass('file-input-new');
  1048 + }
  1049 + },
  1050 + initPreviewDeletes: function () {
  1051 + var self = this, deleteExtraData = self.deleteExtraData || {},
  1052 + resetProgress = function () {
  1053 + var hasFiles = self.isUploadable ? previewCache.count(self.id) : self.$element.get(0).files.length;
  1054 + if (self.$preview.find('.kv-file-remove').length === 0 && !hasFiles) {
  1055 + self.reset();
  1056 + self.initialCaption = '';
  1057 + }
  1058 + };
  1059 +
  1060 + self.$preview.find('.kv-file-remove').each(function () {
  1061 + var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key');
  1062 + if (isEmpty(vUrl) || vKey === undefined) {
  1063 + return;
  1064 + }
  1065 + var $frame = $el.closest('.file-preview-frame'), cache = previewCache.data[self.id],
  1066 + settings, params, index = $frame.data('fileindex'), config, extraData;
  1067 + index = parseInt(index.replace('init_', ''));
  1068 + config = isEmpty(cache.config) && isEmpty(cache.config[index]) ? null : cache.config[index];
  1069 + extraData = isEmpty(config) || isEmpty(config.extra) ? deleteExtraData : config.extra;
  1070 + if (typeof extraData === "function") {
  1071 + extraData = extraData();
  1072 + }
  1073 + params = {id: $el.attr('id'), key: vKey, extra: extraData};
  1074 + settings = $.extend({
  1075 + url: vUrl,
  1076 + type: 'POST',
  1077 + dataType: 'json',
  1078 + data: $.extend({key: vKey}, extraData),
  1079 + beforeSend: function (jqXHR) {
  1080 + self.ajaxAborted = false;
  1081 + self.raise('filepredelete', [vKey, jqXHR, extraData]);
  1082 + if (self.ajaxAborted) {
  1083 + jqXHR.abort();
  1084 + } else {
  1085 + addCss($frame, 'file-uploading');
  1086 + addCss($el, 'disabled');
  1087 + }
  1088 + },
  1089 + success: function (data, textStatus, jqXHR) {
  1090 + var n, cap;
  1091 + if (isEmpty(data) || isEmpty(data.error)) {
  1092 + previewCache.unset(self.id, index);
  1093 + n = previewCache.count(self.id);
  1094 + cap = n > 0 ? self.getMsgSelected(n) : '';
  1095 + self.raise('filedeleted', [vKey, jqXHR, extraData]);
  1096 + self.setCaption(cap);
  1097 + } else {
  1098 + params.jqXHR = jqXHR;
  1099 + params.response = data;
  1100 + self.showError(data.error, params, 'filedeleteerror');
  1101 + $frame.removeClass('file-uploading');
  1102 + $el.removeClass('disabled');
  1103 + resetProgress();
  1104 + return;
  1105 + }
  1106 + $frame.removeClass('file-uploading').addClass('file-deleted');
  1107 + $frame.fadeOut('slow', function () {
  1108 + self.clearObjects($frame);
  1109 + $frame.remove();
  1110 + resetProgress();
  1111 + if (!n && self.getFileStack().length === 0) {
  1112 + self.setCaption('');
  1113 + self.reset();
  1114 + }
  1115 + });
  1116 + },
  1117 + error: function (jqXHR, textStatus, errorThrown) {
  1118 + var errMsg = self.parseError(jqXHR, errorThrown);
  1119 + params.jqXHR = jqXHR;
  1120 + params.response = {};
  1121 + self.showError(errMsg, params, 'filedeleteerror');
  1122 + $frame.removeClass('file-uploading');
  1123 + resetProgress();
  1124 + }
  1125 + }, self.ajaxDeleteSettings);
  1126 + handler($el, 'click', function () {
  1127 + if (!self.validateMinCount()) {
  1128 + return false;
  1129 + }
  1130 + $.ajax(settings);
  1131 + });
  1132 + });
  1133 + },
  1134 + clearObjects: function ($el) {
  1135 + $el.find('video audio').each(function () {
  1136 + this.pause();
  1137 + $(this).remove();
  1138 + });
  1139 + $el.find('img object div').each(function () {
  1140 + $(this).remove();
  1141 + });
  1142 + },
  1143 + clearFileInput: function () {
  1144 + var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
  1145 + if (isEmpty($el.val())) {
  1146 + return;
  1147 + }
  1148 + // Fix for IE ver < 11, that does not clear file inputs
  1149 + // Requires a sequence of steps to prevent IE crashing but
  1150 + // still allow clearing of the file input.
  1151 + if (self.isIE9 || self.isIE10) {
  1152 + $srcFrm = $el.closest('form');
  1153 + $tmpFrm = $(document.createElement('form'));
  1154 + $tmpEl = $(document.createElement('div'));
  1155 + $el.before($tmpEl);
  1156 + if ($srcFrm.length) {
  1157 + $srcFrm.after($tmpFrm);
  1158 + } else {
  1159 + $tmpEl.after($tmpFrm);
  1160 + }
  1161 + $tmpFrm.append($el).trigger('reset');
  1162 + $tmpEl.before($el).remove();
  1163 + $tmpFrm.remove();
  1164 + } else { // normal input clear behavior for other sane browsers
  1165 + $el.val('');
  1166 + }
  1167 + self.fileInputCleared = true;
  1168 + },
  1169 + resetUpload: function () {
  1170 + var self = this;
  1171 + self.uploadCache = {content: [], config: [], tags: [], append: true};
  1172 + self.uploadCount = 0;
  1173 + self.uploadStatus = {};
  1174 + self.uploadLog = [];
  1175 + self.uploadAsyncCount = 0;
  1176 + self.loadedImages = [];
  1177 + self.totalImagesCount = 0;
  1178 + self.$btnUpload.removeAttr('disabled');
  1179 + self.setProgress(0);
  1180 + addCss(self.$progress, 'hide');
  1181 + self.resetErrors(false);
  1182 + self.ajaxAborted = false;
  1183 + self.ajaxRequests = [];
  1184 + self.resetCanvas();
  1185 + },
  1186 + resetCanvas: function () {
  1187 + var self = this;
  1188 + if (self.canvas && self.imageCanvasContext) {
  1189 + self.imageCanvasContext.clearRect(0, 0, self.canvas.width, self.canvas.height);
  1190 + }
  1191 + },
  1192 + cancel: function () {
  1193 + var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
  1194 + if (len > 0) {
  1195 + for (i = 0; i < len; i += 1) {
  1196 + self.cancelling = true;
  1197 + xhr[i].abort();
  1198 + }
  1199 + }
  1200 + self.getThumbs().each(function () {
  1201 + var $thumb = $(this), ind = $thumb.attr('data-fileindex');
  1202 + $thumb.removeClass('file-uploading');
  1203 + if (self.filestack[ind] !== undefined) {
  1204 + $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
  1205 + $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
  1206 + }
  1207 + self.unlock();
  1208 + });
  1209 + },
  1210 + cleanMemory: function ($thumb) {
  1211 + var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
  1212 + /** @namespace objUrl.revokeObjectURL */
  1213 + objUrl.revokeObjectURL(data);
  1214 + },
  1215 + hasInitialPreview: function () {
  1216 + var self = this;
  1217 + return !self.overwriteInitial && previewCache.count(self.id);
  1218 + },
  1219 + clear: function () {
  1220 + var self = this, cap;
  1221 + self.$btnUpload.removeAttr('disabled');
  1222 + self.getThumbs().find('video,audio,img').each(function () {
  1223 + self.cleanMemory($(this));
  1224 + });
  1225 + self.resetUpload();
  1226 + self.clearStack();
  1227 + self.clearFileInput();
  1228 + self.resetErrors(true);
  1229 + self.raise('fileclear');
  1230 + if (self.hasInitialPreview()) {
  1231 + self.showFileIcon();
  1232 + self.resetPreview();
  1233 + self.initPreviewDeletes();
  1234 + self.$container.removeClass('file-input-new');
  1235 + } else {
  1236 + self.getThumbs().each(function () {
  1237 + self.clearObjects($(this));
  1238 + });
  1239 + if (self.isUploadable) {
  1240 + previewCache.data[self.id] = {};
  1241 + }
  1242 + self.$preview.html('');
  1243 + cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
  1244 + self.setCaption(cap);
  1245 + self.$caption.attr('title', '');
  1246 + addCss(self.$container, 'file-input-new');
  1247 + self.validateDefaultPreview();
  1248 + }
  1249 + if (self.$container.find('.file-preview-frame').length === 0) {
  1250 + if (!self.initCaption()) {
  1251 + self.$captionContainer.find('.kv-caption-icon').hide();
  1252 + }
  1253 + }
  1254 + self.hideFileIcon();
  1255 + self.raise('filecleared');
  1256 + self.$captionContainer.focus();
  1257 + self.setFileDropZoneTitle();
  1258 + },
  1259 + resetPreview: function () {
  1260 + var self = this, out, cap;
  1261 + if (previewCache.count(self.id)) {
  1262 + out = previewCache.out(self.id);
  1263 + self.$preview.html(out.content);
  1264 + cap = self.initialCaption ? self.initialCaption : out.caption;
  1265 + self.setCaption(cap);
  1266 + } else {
  1267 + self.clearPreview();
  1268 + self.initCaption();
  1269 + }
  1270 + },
  1271 + clearDefaultPreview: function () {
  1272 + var self = this;
  1273 + self.$preview.find('.file-default-preview').remove();
  1274 + },
  1275 + validateDefaultPreview: function () {
  1276 + var self = this;
  1277 + if (!self.showPreview || isEmpty(self.defaultPreviewContent)) {
  1278 + return;
  1279 + }
  1280 + self.$preview.html('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
  1281 + self.$container.removeClass('file-input-new');
  1282 + },
  1283 + resetPreviewThumbs: function (isAjax) {
  1284 + var self = this, out;
  1285 + if (isAjax) {
  1286 + self.clearPreview();
  1287 + self.clearStack();
  1288 + return;
  1289 + }
  1290 + if (self.hasInitialPreview()) {
  1291 + out = previewCache.out(self.id);
  1292 + self.$preview.html(out.content);
  1293 + self.setCaption(out.caption);
  1294 + self.initPreviewDeletes();
  1295 + } else {
  1296 + self.clearPreview();
  1297 + }
  1298 + },
  1299 + reset: function () {
  1300 + var self = this;
  1301 + self.resetPreview();
  1302 + self.$container.find('.fileinput-filename').text('');
  1303 + self.raise('filereset');
  1304 + addCss(self.$container, 'file-input-new');
  1305 + if (self.$preview.find('.file-preview-frame').length || self.isUploadable && self.dropZoneEnabled) {
  1306 + self.$container.removeClass('file-input-new');
  1307 + }
  1308 + self.setFileDropZoneTitle();
  1309 + self.clearStack();
  1310 + self.formdata = {};
  1311 + },
  1312 + disable: function () {
  1313 + var self = this;
  1314 + self.isDisabled = true;
  1315 + self.raise('filedisabled');
  1316 + self.$element.attr('disabled', 'disabled');
  1317 + self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
  1318 + self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button").attr(
  1319 + "disabled",
  1320 + true);
  1321 + self.initDragDrop();
  1322 + },
  1323 + enable: function () {
  1324 + var self = this;
  1325 + self.isDisabled = false;
  1326 + self.raise('fileenabled');
  1327 + self.$element.removeAttr('disabled');
  1328 + self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
  1329 + self.$container.find(
  1330 + ".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button").removeAttr("disabled");
  1331 + self.initDragDrop();
  1332 + },
  1333 + getThumbs: function (css) {
  1334 + css = css || '';
  1335 + return this.$preview.find('.file-preview-frame:not(.file-preview-initial)' + css);
  1336 + },
  1337 + getExtraData: function (previewId, index) {
  1338 + var self = this, data = self.uploadExtraData;
  1339 + if (typeof self.uploadExtraData === "function") {
  1340 + data = self.uploadExtraData(previewId, index);
  1341 + }
  1342 + return data;
  1343 + },
  1344 + uploadExtra: function (previewId, index) {
  1345 + var self = this, data = self.getExtraData(previewId, index);
  1346 + if (data.length === 0) {
  1347 + return;
  1348 + }
  1349 + $.each(data, function (key, value) {
  1350 + self.formdata.append(key, value);
  1351 + });
  1352 + },
  1353 + setAsyncUploadStatus: function (previewId, pct, total) {
  1354 + var self = this, sum = 0;
  1355 + self.setProgress(pct, $('#' + previewId).find('.file-thumb-progress'));
  1356 + self.uploadStatus[previewId] = pct;
  1357 + $.each(self.uploadStatus, function (key, value) {
  1358 + sum += value;
  1359 + });
  1360 + self.setProgress(Math.ceil(sum / total));
  1361 +
  1362 + },
  1363 + initXhr: function (xhrobj, previewId, fileCount) {
  1364 + var self = this;
  1365 + if (xhrobj.upload) {
  1366 + xhrobj.upload.addEventListener('progress', function (event) {
  1367 + var pct = 0, position = event.loaded || event.position, total = event.total;
  1368 + /** @namespace event.lengthComputable */
  1369 + if (event.lengthComputable) {
  1370 + pct = Math.ceil(position / total * 100);
  1371 + }
  1372 + if (previewId) {
  1373 + self.setAsyncUploadStatus(previewId, pct, fileCount);
  1374 + } else {
  1375 + self.setProgress(Math.ceil(pct));
  1376 + }
  1377 + }, false);
  1378 + }
  1379 + return xhrobj;
  1380 + },
  1381 + ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, previewId, index) {
  1382 + var self = this, settings;
  1383 + self.raise('filepreajax', [previewId, index]);
  1384 + self.uploadExtra(previewId, index);
  1385 + settings = $.extend({
  1386 + xhr: function () {
  1387 + var xhrobj = $.ajaxSettings.xhr();
  1388 + return self.initXhr(xhrobj, previewId, self.getFileStack().length);
  1389 + },
  1390 + url: self.uploadUrl,
  1391 + type: 'POST',
  1392 + dataType: 'json',
  1393 + data: self.formdata,
  1394 + cache: false,
  1395 + processData: false,
  1396 + contentType: false,
  1397 + beforeSend: fnBefore,
  1398 + success: fnSuccess,
  1399 + complete: fnComplete,
  1400 + error: fnError
  1401 + }, self.ajaxSettings);
  1402 + self.ajaxRequests.push($.ajax(settings));
  1403 + },
  1404 + initUploadSuccess: function (out, $thumb, allFiles) {
  1405 + var self = this, append, data, index, $newThumb, content, config, tags, i;
  1406 + if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
  1407 + return;
  1408 + }
  1409 + if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
  1410 + self.hasInitData = true;
  1411 + content = out.initialPreview || [];
  1412 + config = out.initialPreviewConfig || [];
  1413 + tags = out.initialPreviewThumbTags || [];
  1414 + append = out.append === undefined || out.append ? true : false;
  1415 + self.overwriteInitial = false;
  1416 + if ($thumb !== undefined) {
  1417 + if (!allFiles) {
  1418 + index = previewCache.add(self.id, content, config[0], tags[0], append);
  1419 + data = previewCache.get(self.id, index, false);
  1420 + $newThumb = $(data).hide();
  1421 + $thumb.after($newThumb).fadeOut('slow', function () {
  1422 + $newThumb.fadeIn('slow').css('display:inline-block');
  1423 + self.initPreviewDeletes();
  1424 + self.clearFileInput();
  1425 + $thumb.remove();
  1426 + });
  1427 + } else {
  1428 + i = $thumb.attr('data-fileindex');
  1429 + self.uploadCache.content[i] = content[0];
  1430 + self.uploadCache.config[i] = config[0];
  1431 + self.uploadCache.tags[i] = tags[0];
  1432 + self.uploadCache.append = append;
  1433 + }
  1434 + } else {
  1435 + previewCache.set(self.id, content, config, tags, append);
  1436 + self.initPreview();
  1437 + self.initPreviewDeletes();
  1438 + }
  1439 + }
  1440 + },
  1441 + initSuccessThumbs: function () {
  1442 + var self = this;
  1443 + if (!self.showPreview) {
  1444 + return;
  1445 + }
  1446 + self.getThumbs('.file-preview-success').each(function () {
  1447 + var $thumb = $(this), $remove = $thumb.find('.kv-file-remove');
  1448 + $remove.removeAttr('disabled');
  1449 + handler($remove, 'click', function () {
  1450 + var out = self.raise('filesuccessremove', [$thumb.attr('id'), $thumb.data('fileindex')]);
  1451 + self.cleanMemory($thumb);
  1452 + if (out === false) {
  1453 + return;
  1454 + }
  1455 + $thumb.fadeOut('slow', function () {
  1456 + $thumb.remove();
  1457 + if (!self.$preview.find('.file-preview-frame').length) {
  1458 + self.reset();
  1459 + }
  1460 + });
  1461 + });
  1462 + });
  1463 + },
  1464 + checkAsyncComplete: function () {
  1465 + var self = this, previewId, i;
  1466 + for (i = 0; i < self.filestack.length; i++) {
  1467 + if (self.filestack[i]) {
  1468 + previewId = self.previewInitId + "-" + i;
  1469 + if ($.inArray(previewId, self.uploadLog) === -1) {
  1470 + return false;
  1471 + }
  1472 + }
  1473 + }
  1474 + return (self.uploadAsyncCount === self.uploadLog.length);
  1475 + },
  1476 + uploadSingle: function (i, files, allFiles) {
  1477 + var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
  1478 + previewId = self.previewInitId + "-" + i, $thumb, chkComplete, $btnUpload, $btnDelete,
  1479 + hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  1480 + fnBefore, fnSuccess, fnComplete, fnError, updateUploadLog, params = {id: previewId, index: i};
  1481 + self.formdata = formdata;
  1482 + if (self.showPreview) {
  1483 + $thumb = $('#' + previewId + ':not(.file-preview-initial)');
  1484 + $btnUpload = $thumb.find('.kv-file-upload');
  1485 + $btnDelete = $thumb.find('.kv-file-remove');
  1486 + $('#' + previewId).find('.file-thumb-progress').removeClass('hide');
  1487 + }
  1488 + if (total === 0 || !hasPostData || ($btnUpload && $btnUpload.hasClass('disabled')) || self.abort(params)) {
  1489 + return;
  1490 + }
  1491 + updateUploadLog = function (i, previewId) {
  1492 + self.updateStack(i, undefined);
  1493 + self.uploadLog.push(previewId);
  1494 + if (self.checkAsyncComplete()) {
  1495 + self.fileBatchCompleted = true;
  1496 + }
  1497 + };
  1498 + chkComplete = function () {
  1499 + if (!self.fileBatchCompleted) {
  1500 + return;
  1501 + }
  1502 + setTimeout(function () {
  1503 + if (self.showPreview) {
  1504 + previewCache.set(
  1505 + self.id,
  1506 + self.uploadCache.content,
  1507 + self.uploadCache.config,
  1508 + self.uploadCache.tags,
  1509 + self.uploadCache.append
  1510 + );
  1511 + if (self.hasInitData) {
  1512 + self.initPreview();
  1513 + self.initPreviewDeletes();
  1514 + }
  1515 + }
  1516 + self.unlock();
  1517 + self.clearFileInput();
  1518 + self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
  1519 + self.uploadCount = 0;
  1520 + self.uploadStatus = {};
  1521 + self.uploadLog = [];
  1522 + self.setProgress(100);
  1523 + }, 100);
  1524 + };
  1525 + fnBefore = function (jqXHR) {
  1526 + outData = self.getOutData(jqXHR);
  1527 + self.fileBatchCompleted = false;
  1528 + if (self.showPreview) {
  1529 + if (!$thumb.hasClass('file-preview-success')) {
  1530 + self.setThumbStatus($thumb, 'Loading');
  1531 + addCss($thumb, 'file-uploading');
  1532 + }
  1533 + $btnUpload.attr('disabled', true);
  1534 + $btnDelete.attr('disabled', true);
  1535 + }
  1536 + if (!allFiles) {
  1537 + self.lock();
  1538 + }
  1539 + self.raise('filepreupload', [outData, previewId, i]);
  1540 + params = $.extend(params, outData);
  1541 + if (self.abort(params)) {
  1542 + jqXHR.abort();
  1543 + self.setProgress(100);
  1544 + }
  1545 + };
  1546 + fnSuccess = function (data, textStatus, jqXHR) {
  1547 + outData = self.getOutData(jqXHR, data);
  1548 + params = $.extend(params, outData);
  1549 + setTimeout(function () {
  1550 + if (isEmpty(data) || isEmpty(data.error)) {
  1551 + if (self.showPreview) {
  1552 + self.setThumbStatus($thumb, 'Success');
  1553 + $btnUpload.hide();
  1554 + self.initUploadSuccess(data, $thumb, allFiles);
  1555 + }
  1556 + self.raise('fileuploaded', [outData, previewId, i]);
  1557 + if (!allFiles) {
  1558 + self.updateStack(i, undefined);
  1559 + } else {
  1560 + updateUploadLog(i, previewId);
  1561 + }
  1562 + } else {
  1563 + self.setThumbStatus($thumb, 'Error');
  1564 + self.showUploadError(data.error, params);
  1565 + if (allFiles) {
  1566 + updateUploadLog(i, previewId);
  1567 + }
  1568 + }
  1569 + }, 100);
  1570 + };
  1571 + fnComplete = function () {
  1572 + setTimeout(function () {
  1573 + if (self.showPreview) {
  1574 + $btnUpload.removeAttr('disabled');
  1575 + $btnDelete.removeAttr('disabled');
  1576 + $thumb.removeClass('file-uploading');
  1577 + }
  1578 + if (!allFiles) {
  1579 + self.unlock(false);
  1580 + self.clearFileInput();
  1581 + } else {
  1582 + chkComplete();
  1583 + }
  1584 + self.initSuccessThumbs();
  1585 + }, 100);
  1586 + };
  1587 + fnError = function (jqXHR, textStatus, errorThrown) {
  1588 + var errMsg = self.parseError(jqXHR, errorThrown, (allFiles ? files[i].name : null));
  1589 + setTimeout(function () {
  1590 + if (allFiles) {
  1591 + updateUploadLog(i, previewId);
  1592 + }
  1593 + self.uploadStatus[previewId] = 100;
  1594 + self.setThumbStatus($thumb, 'Error');
  1595 + params = $.extend(params, self.getOutData(jqXHR));
  1596 + self.showUploadError(errMsg, params);
  1597 + }, 100);
  1598 + };
  1599 + formdata.append(self.uploadFileAttr, files[i], self.filenames[i]);
  1600 + formdata.append('file_id', i);
  1601 + self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i);
  1602 + },
  1603 + uploadBatch: function () {
  1604 + var self = this, files = self.filestack, total = files.length, params = {},
  1605 + hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  1606 + setAllUploaded, fnBefore, fnSuccess, fnComplete, fnError;
  1607 + self.formdata = new FormData();
  1608 + if (total === 0 || !hasPostData || self.abort(params)) {
  1609 + return;
  1610 + }
  1611 + setAllUploaded = function () {
  1612 + $.each(files, function (key) {
  1613 + self.updateStack(key, undefined);
  1614 + });
  1615 + self.clearFileInput();
  1616 + };
  1617 + fnBefore = function (jqXHR) {
  1618 + self.lock();
  1619 + var outData = self.getOutData(jqXHR);
  1620 + if (self.showPreview) {
  1621 + self.getThumbs().each(function () {
  1622 + var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
  1623 + $btnDelete = $thumb.find('.kv-file-remove');
  1624 + if (!$thumb.hasClass('file-preview-success')) {
  1625 + self.setThumbStatus($thumb, 'Loading');
  1626 + addCss($thumb, 'file-uploading');
  1627 + }
  1628 + $btnUpload.attr('disabled', true);
  1629 + $btnDelete.attr('disabled', true);
  1630 + });
  1631 + }
  1632 + self.raise('filebatchpreupload', [outData]);
  1633 + if (self.abort(outData)) {
  1634 + jqXHR.abort();
  1635 + self.setProgress(100);
  1636 + }
  1637 + };
  1638 + fnSuccess = function (data, textStatus, jqXHR) {
  1639 + /** @namespace data.errorkeys */
  1640 + var outData = self.getOutData(jqXHR, data), $thumbs = self.getThumbs(), key = 0,
  1641 + keys = isEmpty(data) || isEmpty(data.errorkeys) ? [] : data.errorkeys;
  1642 + if (isEmpty(data) || isEmpty(data.error)) {
  1643 + self.raise('filebatchuploadsuccess', [outData]);
  1644 + setAllUploaded();
  1645 + if (self.showPreview) {
  1646 + $thumbs.each(function () {
  1647 + var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload');
  1648 + $thumb.find('.kv-file-upload').hide();
  1649 + self.setThumbStatus($thumb, 'Success');
  1650 + $thumb.removeClass('file-uploading');
  1651 + $btnUpload.removeAttr('disabled');
  1652 + });
  1653 + self.initUploadSuccess(data);
  1654 + } else {
  1655 + self.reset();
  1656 + }
  1657 + } else {
  1658 + if (self.showPreview) {
  1659 + $thumbs.each(function () {
  1660 + var $thumb = $(this), $btnDelete = $thumb.find('.kv-file-remove'),
  1661 + $btnUpload = $thumb.find('.kv-file-upload');
  1662 + $thumb.removeClass('file-uploading');
  1663 + $btnUpload.removeAttr('disabled');
  1664 + $btnDelete.removeAttr('disabled');
  1665 + if (keys.length === 0) {
  1666 + self.setThumbStatus($thumb, 'Error');
  1667 + return;
  1668 + }
  1669 + if ($.inArray(key, keys) !== -1) {
  1670 + self.setThumbStatus($thumb, 'Error');
  1671 + } else {
  1672 + $thumb.find('.kv-file-upload').hide();
  1673 + self.setThumbStatus($thumb, 'Success');
  1674 + self.updateStack(key, undefined);
  1675 + }
  1676 + key++;
  1677 + });
  1678 + self.initUploadSuccess(data);
  1679 + }
  1680 + self.showUploadError(data.error, outData, 'filebatchuploaderror');
  1681 + }
  1682 + };
  1683 + fnComplete = function () {
  1684 + self.setProgress(100);
  1685 + self.unlock();
  1686 + self.initSuccessThumbs();
  1687 + self.clearFileInput();
  1688 + self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
  1689 + };
  1690 + fnError = function (jqXHR, textStatus, errorThrown) {
  1691 + var outData = self.getOutData(jqXHR), errMsg = self.parseError(jqXHR, errorThrown);
  1692 + self.showUploadError(errMsg, outData, 'filebatchuploaderror');
  1693 + self.uploadFileCount = total - 1;
  1694 + if (!self.showPreview) {
  1695 + return;
  1696 + }
  1697 + self.getThumbs().each(function () {
  1698 + var $thumb = $(this), key = $thumb.attr('data-fileindex');
  1699 + $thumb.removeClass('file-uploading');
  1700 + if (self.filestack[key] !== undefined) {
  1701 + self.setThumbStatus($thumb, 'Error');
  1702 + }
  1703 + });
  1704 + self.getThumbs().removeClass('file-uploading');
  1705 + self.getThumbs(' .kv-file-upload').removeAttr('disabled');
  1706 + self.getThumbs(' .kv-file-delete').removeAttr('disabled');
  1707 + };
  1708 + $.each(files, function (key, data) {
  1709 + if (!isEmpty(files[key])) {
  1710 + self.formdata.append(self.uploadFileAttr, data, self.filenames[key]);
  1711 + }
  1712 + });
  1713 + self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  1714 + },
  1715 + uploadExtraOnly: function () {
  1716 + var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
  1717 + self.formdata = new FormData();
  1718 + if (self.abort(params)) {
  1719 + return;
  1720 + }
  1721 + fnBefore = function (jqXHR) {
  1722 + self.lock();
  1723 + var outData = self.getOutData(jqXHR);
  1724 + self.raise('filebatchpreupload', [outData]);
  1725 + self.setProgress(50);
  1726 + params.data = outData;
  1727 + params.xhr = jqXHR;
  1728 + if (self.abort(params)) {
  1729 + jqXHR.abort();
  1730 + self.setProgress(100);
  1731 + }
  1732 + };
  1733 + fnSuccess = function (data, textStatus, jqXHR) {
  1734 + var outData = self.getOutData(jqXHR, data);
  1735 + if (isEmpty(data) || isEmpty(data.error)) {
  1736 + self.raise('filebatchuploadsuccess', [outData]);
  1737 + self.clearFileInput();
  1738 + self.initUploadSuccess(data);
  1739 + } else {
  1740 + self.showUploadError(data.error, outData, 'filebatchuploaderror');
  1741 + }
  1742 + };
  1743 + fnComplete = function () {
  1744 + self.setProgress(100);
  1745 + self.unlock();
  1746 + self.clearFileInput();
  1747 + self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
  1748 + };
  1749 + fnError = function (jqXHR, textStatus, errorThrown) {
  1750 + var outData = self.getOutData(jqXHR), errMsg = self.parseError(jqXHR, errorThrown);
  1751 + params.data = outData;
  1752 + self.showUploadError(errMsg, outData, 'filebatchuploaderror');
  1753 + };
  1754 + self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  1755 + },
  1756 + upload: function () {
  1757 + var self = this, totLen = self.getFileStack().length, params = {},
  1758 + i, outData, len, hasExtraData = !$.isEmptyObject(self.getExtraData());
  1759 + if (self.minFileCount > 0 && self.getFileCount(totLen) < self.minFileCount) {
  1760 + self.noFilesError(params);
  1761 + return;
  1762 + }
  1763 + if (!self.isUploadable || self.isDisabled || (totLen === 0 && !hasExtraData)) {
  1764 + return;
  1765 + }
  1766 + self.resetUpload();
  1767 + self.$progress.removeClass('hide');
  1768 + self.uploadCount = 0;
  1769 + self.uploadStatus = {};
  1770 + self.uploadLog = [];
  1771 + self.lock();
  1772 + self.setProgress(2);
  1773 + if (totLen === 0 && hasExtraData) {
  1774 + self.uploadExtraOnly();
  1775 + return;
  1776 + }
  1777 + len = self.filestack.length;
  1778 + self.hasInitData = false;
  1779 + if (self.uploadAsync) {
  1780 + outData = self.getOutData();
  1781 + self.raise('filebatchpreupload', [outData]);
  1782 + self.fileBatchCompleted = false;
  1783 + self.uploadCache = {content: [], config: [], tags: [], append: true};
  1784 + self.uploadAsyncCount = self.getFileStack().length;
  1785 + for (i = 0; i < len; i++) {
  1786 + self.uploadCache.content[i] = null;
  1787 + self.uploadCache.config[i] = null;
  1788 + self.uploadCache.tags[i] = null;
  1789 + }
  1790 + for (i = 0; i < len; i++) {
  1791 + if (self.filestack[i] !== undefined) {
  1792 + self.uploadSingle(i, self.filestack, true);
  1793 + }
  1794 + }
  1795 + return;
  1796 + }
  1797 + self.uploadBatch();
  1798 + },
  1799 + initFileActions: function () {
  1800 + var self = this;
  1801 + if (!self.showPreview) {
  1802 + return;
  1803 + }
  1804 + self.$preview.find('.kv-file-remove').each(function () {
  1805 + var $el = $(this), $frame = $el.closest('.file-preview-frame'), hasError,
  1806 + id = $frame.attr('id'), ind = $frame.attr('data-fileindex'), n, cap, status;
  1807 + handler($el, 'click', function () {
  1808 + status = self.raise('filepreremove', [id, ind]);
  1809 + if (status === false || !self.validateMinCount()) {
  1810 + return false;
  1811 + }
  1812 + hasError = $frame.hasClass('file-preview-error');
  1813 + self.cleanMemory($frame);
  1814 + $frame.fadeOut('slow', function () {
  1815 + self.updateStack(ind, undefined);
  1816 + self.clearObjects($frame);
  1817 + $frame.remove();
  1818 + if (id && hasError) {
  1819 + self.$errorContainer.find('li[data-file-id="' + id + '"]').fadeOut('fast', function () {
  1820 + $(this).remove();
  1821 + if (!self.errorsExist()) {
  1822 + self.resetErrors();
  1823 + }
  1824 + });
  1825 + }
  1826 + var filestack = self.getFileStack(true), len = filestack.length, chk = previewCache.count(
  1827 + self.id),
  1828 + hasThumb = self.showPreview && self.$preview.find('.file-preview-frame').length;
  1829 + self.clearFileInput();
  1830 + if (len === 0 && chk === 0 && !hasThumb) {
  1831 + self.reset();
  1832 + } else {
  1833 + n = chk + len;
  1834 + cap = n > 1 ? self.getMsgSelected(n) : (filestack[0] ? self.getFileNames()[0] : '');
  1835 + self.setCaption(cap);
  1836 + }
  1837 + self.raise('fileremoved', [id, ind]);
  1838 + });
  1839 + });
  1840 + });
  1841 + self.$preview.find('.kv-file-upload').each(function () {
  1842 + var $el = $(this);
  1843 + handler($el, 'click', function () {
  1844 + var $frame = $el.closest('.file-preview-frame'),
  1845 + ind = $frame.attr('data-fileindex');
  1846 + if (!$frame.hasClass('file-preview-error')) {
  1847 + self.uploadSingle(ind, self.filestack, false);
  1848 + }
  1849 + });
  1850 + });
  1851 + },
  1852 + hideFileIcon: function () {
  1853 + if (this.overwriteInitial) {
  1854 + this.$captionContainer.find('.kv-caption-icon').hide();
  1855 + }
  1856 + },
  1857 + showFileIcon: function () {
  1858 + this.$captionContainer.find('.kv-caption-icon').show();
  1859 + },
  1860 + addError: function (msg) {
  1861 + var self = this, $error = self.$errorContainer;
  1862 + if (msg && $error.length) {
  1863 + $error.html(self.errorCloseButton + msg);
  1864 + $error.find('.kv-error-close').off('click').on('click', function () {
  1865 + $error.fadeOut('slow');
  1866 + });
  1867 + }
  1868 + },
  1869 + resetErrors: function (fade) {
  1870 + var self = this, $error = self.$errorContainer;
  1871 + self.isError = false;
  1872 + self.$container.removeClass('has-error');
  1873 + $error.html('');
  1874 + if (fade) {
  1875 + $error.fadeOut('slow');
  1876 + } else {
  1877 + $error.hide();
  1878 + }
  1879 + },
  1880 + showFolderError: function (folders) {
  1881 + var self = this, $error = self.$errorContainer;
  1882 + if (!folders) {
  1883 + return;
  1884 + }
  1885 + self.addError(self.msgFoldersNotAllowed.replace(/\{n}/g, folders));
  1886 + $error.fadeIn(800);
  1887 + addCss(self.$container, 'has-error');
  1888 + self.raise('filefoldererror', [folders]);
  1889 + },
  1890 + showUploadError: function (msg, params, event) {
  1891 + var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror',
  1892 + e = params && params.id ? '<li data-file-id="' + params.id + '">' + msg + '</li>' : '<li>' + msg + '</li>';
  1893 + if ($error.find('ul').length === 0) {
  1894 + self.addError('<ul>' + e + '</ul>');
  1895 + } else {
  1896 + $error.find('ul').append(e);
  1897 + }
  1898 + $error.fadeIn(800);
  1899 + self.raise(ev, [params]);
  1900 + self.$container.removeClass('file-input-new');
  1901 + addCss(self.$container, 'has-error');
  1902 + return true;
  1903 + },
  1904 + showError: function (msg, params, event) {
  1905 + var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
  1906 + params = params || {};
  1907 + params.reader = self.reader;
  1908 + self.addError(msg);
  1909 + $error.fadeIn(800);
  1910 + self.raise(ev, [params]);
  1911 + if (!self.isUploadable) {
  1912 + self.clearFileInput();
  1913 + }
  1914 + self.$container.removeClass('file-input-new');
  1915 + addCss(self.$container, 'has-error');
  1916 + self.$btnUpload.attr('disabled', true);
  1917 + return true;
  1918 + },
  1919 + errorHandler: function (evt, caption) {
  1920 + var self = this, err = evt.target.error;
  1921 + /** @namespace err.NOT_FOUND_ERR */
  1922 + /** @namespace err.SECURITY_ERR */
  1923 + /** @namespace err.NOT_READABLE_ERR */
  1924 + if (err.code === err.NOT_FOUND_ERR) {
  1925 + self.showError(self.msgFileNotFound.replace('{name}', caption));
  1926 + } else if (err.code === err.SECURITY_ERR) {
  1927 + self.showError(self.msgFileSecured.replace('{name}', caption));
  1928 + } else if (err.code === err.NOT_READABLE_ERR) {
  1929 + self.showError(self.msgFileNotReadable.replace('{name}', caption));
  1930 + } else if (err.code === err.ABORT_ERR) {
  1931 + self.showError(self.msgFilePreviewAborted.replace('{name}', caption));
  1932 + } else {
  1933 + self.showError(self.msgFilePreviewError.replace('{name}', caption));
  1934 + }
  1935 + },
  1936 + parseFileType: function (file) {
  1937 + var self = this, isValid, vType, cat, i;
  1938 + for (i = 0; i < defaultPreviewTypes.length; i += 1) {
  1939 + cat = defaultPreviewTypes[i];
  1940 + isValid = isSet(cat, self.fileTypeSettings) ? self.fileTypeSettings[cat] : defaultFileTypeSettings[cat];
  1941 + vType = isValid(file.type, file.name) ? cat : '';
  1942 + if (!isEmpty(vType)) {
  1943 + return vType;
  1944 + }
  1945 + }
  1946 + return 'other';
  1947 + },
  1948 + previewDefault: function (file, previewId, isDisabled) {
  1949 + if (!this.showPreview) {
  1950 + return;
  1951 + }
  1952 + var self = this, frameClass = '', fname = file ? file.name : '',
  1953 + /** @namespace objUrl.createObjectURL */
  1954 + data = objUrl.createObjectURL(file), ind = previewId.slice(previewId.lastIndexOf('-') + 1),
  1955 + config = self.previewSettings.other || defaultPreviewSettings.other,
  1956 + footer = self.renderFileFooter(file.name, config.width),
  1957 + previewOtherTemplate = self.parseFilePreviewIcon(self.getPreviewTemplate('other'), fname);
  1958 + if (isDisabled === true) {
  1959 + if (!self.isUploadable) {
  1960 + footer += '<div class="file-other-error" title="' + self.fileActionSettings.indicatorErrorTitle +
  1961 + '">' + self.fileActionSettings.indicatorError + '</div>';
  1962 + }
  1963 + }
  1964 + self.clearDefaultPreview();
  1965 + self.$preview.append("\n" + previewOtherTemplate
  1966 + .replace(/\{previewId}/g, previewId)
  1967 + .replace(/\{frameClass}/g, frameClass)
  1968 + .replace(/\{fileindex}/g, ind)
  1969 + .replace(/\{caption}/g, self.slug(file.name))
  1970 + .replace(/\{width}/g, config.width)
  1971 + .replace(/\{height}/g, config.height)
  1972 + .replace(/\{type}/g, file.type)
  1973 + .replace(/\{data}/g, data)
  1974 + .replace(/\{footer}/g, footer));
  1975 + if (isDisabled === true && self.isUploadable) {
  1976 + self.setThumbStatus($('#' + previewId), 'Error');
  1977 + }
  1978 + },
  1979 + previewFile: function (i, file, theFile, previewId, data) {
  1980 + if (!this.showPreview) {
  1981 + return;
  1982 + }
  1983 + var self = this, cat = self.parseFileType(file), fname = file ? file.name : '', caption = self.slug(fname),
  1984 + content, strText, types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes,
  1985 + tmplt = self.getPreviewTemplate(cat), chkTypes = types && types.indexOf(cat) >= 0, id,
  1986 + config = isSet(cat, self.previewSettings) ? self.previewSettings[cat] : defaultPreviewSettings[cat],
  1987 + chkMimes = mimes && mimes.indexOf(file.type) !== -1,
  1988 + footer = self.renderFileFooter(caption, config.width), modal = '',
  1989 + ind = previewId.slice(previewId.lastIndexOf('-') + 1);
  1990 + if (chkTypes || chkMimes) {
  1991 + tmplt = self.parseFilePreviewIcon(tmplt, fname.split('.').pop());
  1992 + if (cat === 'text') {
  1993 + strText = htmlEncode(theFile.target.result);
  1994 + id = 'text-' + uniqId();
  1995 + content = tmplt.replace(/\{zoom}/g, self.getLayoutTemplate('zoom'));
  1996 + modal = self.getLayoutTemplate('modal').replace('{id}', id)
  1997 + .replace(/\{title}/g, caption)
  1998 + .replace(/\{body}/g, strText).replace(/\{heading}/g, self.msgZoomModalHeading);
  1999 + content = content.replace(/\{previewId}/g, previewId).replace(/\{caption}/g, caption)
  2000 + .replace(/\{width}/g, config.width).replace(/\{height}/g, config.height)
  2001 + .replace(/\{frameClass}/g, '').replace(/\{zoomInd}/g, self.zoomIndicator)
  2002 + .replace(/\{footer}/g, footer).replace(/\{fileindex}/g, ind)
  2003 + .replace(/\{type}/g, file.type).replace(/\{zoomTitle}/g, self.msgZoomTitle)
  2004 + .replace(/\{dialog}/g, "$('#" + id + "').modal('show')")
  2005 + .replace(/\{data}/g, strText) + modal;
  2006 + } else {
  2007 + content = tmplt.replace(/\{previewId}/g, previewId).replace(/\{caption}/g, caption)
  2008 + .replace(/\{frameClass}/g, '').replace(/\{type}/g, file.type).replace(/\{fileindex}/g, ind)
  2009 + .replace(/\{width}/g, config.width).replace(/\{height}/g, config.height)
  2010 + .replace(/\{footer}/g, footer).replace(/\{data}/g, data);
  2011 + }
  2012 + self.clearDefaultPreview();
  2013 + self.$preview.append("\n" + content);
  2014 + self.validateImage(i, previewId, caption, file.type);
  2015 + } else {
  2016 + self.previewDefault(file, previewId);
  2017 + }
  2018 + },
  2019 + slugDefault: function (text) {
  2020 + return isEmpty(text) ? '' : text.split(/(\\|\/)/g).pop().replace(/[^\w\u00C0-\u017F\-.\\\/ ]+/g, '');
  2021 + },
  2022 + readFiles: function (files) {
  2023 + this.reader = new FileReader();
  2024 + var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
  2025 + $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
  2026 + msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
  2027 + settings = self.fileTypeSettings, ctr = self.filestack.length, readFile,
  2028 + throwError = function (msg, file, previewId, index) {
  2029 + var p1 = $.extend(self.getOutData({}, {}, files), {id: previewId, index: index}),
  2030 + p2 = {id: previewId, index: index, file: file, files: files};
  2031 + self.previewDefault(file, previewId, true);
  2032 + if (self.isUploadable) {
  2033 + self.pushStack(undefined);
  2034 + }
  2035 + setTimeout(readFile(index + 1), 100);
  2036 + self.initFileActions();
  2037 + return self.isUploadable ? self.showUploadError(msg, p1) : self.showError(msg, p2);
  2038 + };
  2039 +
  2040 + self.loadedImages = [];
  2041 + self.totalImagesCount = 0;
  2042 +
  2043 + $.each(files, function (key, file) {
  2044 + var cat = 'image',
  2045 + func = isSet(cat,
  2046 + self.fileTypeSettings) ? self.fileTypeSettings[cat] : defaultFileTypeSettings[cat];
  2047 + if (func && func(file.type)) {
  2048 + self.totalImagesCount++;
  2049 + }
  2050 + });
  2051 +
  2052 + readFile = function (i) {
  2053 + if (isEmpty($el.attr('multiple'))) {
  2054 + numFiles = 1;
  2055 + }
  2056 + if (i >= numFiles) {
  2057 + if (self.isUploadable && self.filestack.length > 0) {
  2058 + self.raise('filebatchselected', [self.getFileStack()]);
  2059 + } else {
  2060 + self.raise('filebatchselected', [files]);
  2061 + }
  2062 + $container.removeClass('file-thumb-loading');
  2063 + $status.html('');
  2064 + return;
  2065 + }
  2066 + var node = ctr + i, previewId = previewInitId + "-" + node, isText, file = files[i],
  2067 + caption = self.slug(file.name), fileSize = (file.size || 0) / 1000, checkFile, fileExtExpr = '',
  2068 + previewData = objUrl.createObjectURL(file), fileCount = 0, j, msg, typ, chk,
  2069 + fileTypes = self.allowedFileTypes, strTypes = isEmpty(fileTypes) ? '' : fileTypes.join(', '),
  2070 + fileExt = self.allowedFileExtensions, strExt = isEmpty(fileExt) ? '' : fileExt.join(', ');
  2071 + if (!isEmpty(fileExt)) {
  2072 + fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
  2073 + }
  2074 + fileSize = fileSize.toFixed(2);
  2075 + if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
  2076 + msg = self.msgSizeTooLarge.replace('{name}', caption)
  2077 + .replace('{size}', fileSize)
  2078 + .replace('{maxSize}', self.maxFileSize);
  2079 + self.isError = throwError(msg, file, previewId, i);
  2080 + return;
  2081 + }
  2082 + if (!isEmpty(fileTypes) && isArray(fileTypes)) {
  2083 + for (j = 0; j < fileTypes.length; j += 1) {
  2084 + typ = fileTypes[j];
  2085 + checkFile = settings[typ];
  2086 + chk = (checkFile !== undefined && checkFile(file.type, caption));
  2087 + fileCount += isEmpty(chk) ? 0 : chk.length;
  2088 + }
  2089 + if (fileCount === 0) {
  2090 + msg = self.msgInvalidFileType.replace('{name}', caption).replace('{types}', strTypes);
  2091 + self.isError = throwError(msg, file, previewId, i);
  2092 + return;
  2093 + }
  2094 + }
  2095 + if (fileCount === 0 && !isEmpty(fileExt) && isArray(fileExt) && !isEmpty(fileExtExpr)) {
  2096 + chk = caption.match(fileExtExpr);
  2097 + fileCount += isEmpty(chk) ? 0 : chk.length;
  2098 + if (fileCount === 0) {
  2099 + msg = self.msgInvalidFileExtension.replace('{name}', caption).replace('{extensions}',
  2100 + strExt);
  2101 + self.isError = throwError(msg, file, previewId, i);
  2102 + return;
  2103 + }
  2104 + }
  2105 + if (!self.showPreview) {
  2106 + self.pushStack(file);
  2107 + setTimeout(readFile(i + 1), 100);
  2108 + self.raise('fileloaded', [file, previewId, i, reader]);
  2109 + return;
  2110 + }
  2111 + if ($preview.length > 0 && FileReader !== undefined) {
  2112 + $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
  2113 + $container.addClass('file-thumb-loading');
  2114 + reader.onerror = function (evt) {
  2115 + self.errorHandler(evt, caption);
  2116 + };
  2117 + reader.onload = function (theFile) {
  2118 + self.previewFile(i, file, theFile, previewId, previewData);
  2119 + self.initFileActions();
  2120 + };
  2121 + reader.onloadend = function () {
  2122 + msg = msgProgress
  2123 + .replace('{index}', i + 1).replace('{files}', numFiles)
  2124 + .replace('{percent}', 50).replace('{name}', caption);
  2125 + setTimeout(function () {
  2126 + $status.html(msg);
  2127 + self.updateFileDetails(numFiles);
  2128 + readFile(i + 1);
  2129 + }, 100);
  2130 + self.raise('fileloaded', [file, previewId, i, reader]);
  2131 + };
  2132 + reader.onprogress = function (data) {
  2133 + if (data.lengthComputable) {
  2134 + var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
  2135 + msg = msgProgress.replace('{index}', i + 1).replace('{files}', numFiles)
  2136 + .replace('{percent}', progress).replace('{name}', caption);
  2137 + setTimeout(function () {
  2138 + $status.html(msg);
  2139 + }, 100);
  2140 + }
  2141 + };
  2142 + isText = isSet('text', settings) ? settings.text : defaultFileTypeSettings.text;
  2143 + if (isText(file.type, caption)) {
  2144 + reader.readAsText(file, self.textEncoding);
  2145 + } else {
  2146 + reader.readAsArrayBuffer(file);
  2147 + }
  2148 + } else {
  2149 + self.previewDefault(file, previewId);
  2150 + setTimeout(function () {
  2151 + readFile(i + 1);
  2152 + self.updateFileDetails(numFiles);
  2153 + }, 100);
  2154 + self.raise('fileloaded', [file, previewId, i, reader]);
  2155 + }
  2156 + self.pushStack(file);
  2157 + };
  2158 +
  2159 + readFile(0);
  2160 + self.updateFileDetails(numFiles, false);
  2161 + },
  2162 + updateFileDetails: function (numFiles) {
  2163 + var self = this, $el = self.$element, fileStack = self.getFileStack(),
  2164 + name = $el.val() || (fileStack.length && fileStack[0].name) || '', label = self.slug(name),
  2165 + n = self.isUploadable ? fileStack.length : numFiles,
  2166 + nFiles = previewCache.count(self.id) + n,
  2167 + log = n > 1 ? self.getMsgSelected(nFiles) : label;
  2168 + if (self.isError) {
  2169 + self.$previewContainer.removeClass('file-thumb-loading');
  2170 + self.$previewStatus.html('');
  2171 + self.$captionContainer.find('.kv-caption-icon').hide();
  2172 + } else {
  2173 + self.showFileIcon();
  2174 + }
  2175 + self.setCaption(log, self.isError);
  2176 + self.$container.removeClass('file-input-new file-input-ajax-new');
  2177 + if (arguments.length === 1) {
  2178 + self.raise('fileselect', [numFiles, label]);
  2179 + }
  2180 + if (previewCache.count(self.id)) {
  2181 + self.initPreviewDeletes();
  2182 + }
  2183 + },
  2184 + validateMinCount: function () {
  2185 + var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  2186 + if (self.validateInitialCount && self.minFileCount > 0 && self.getFileCount(len - 1) < self.minFileCount) {
  2187 + self.noFilesError({});
  2188 + return false;
  2189 + }
  2190 + return true;
  2191 + },
  2192 + getFileCount: function (fileCount) {
  2193 + var self = this, addCount = 0;
  2194 + if (self.validateInitialCount && !self.overwriteInitial) {
  2195 + addCount = previewCache.count(self.id);
  2196 + fileCount += addCount;
  2197 + }
  2198 + return fileCount;
  2199 + },
  2200 + change: function (e) {
  2201 + var self = this, $el = self.$element;
  2202 + if (!self.isUploadable && isEmpty($el.val()) && self.fileInputCleared) { // IE 11 fix
  2203 + self.fileInputCleared = false;
  2204 + return;
  2205 + }
  2206 + self.fileInputCleared = false;
  2207 + var tfiles, msg, total, isDragDrop = arguments.length > 1,
  2208 + files = isDragDrop ? e.originalEvent.dataTransfer.files : $el.get(0).files,
  2209 + isSingleUpload = isEmpty($el.attr('multiple')), i = 0, f, n, folders = 0,
  2210 + ctr = self.filestack.length, isAjaxUpload = self.isUploadable, len,
  2211 + flagSingle = (isSingleUpload && ctr > 0),
  2212 + throwError = function (mesg, file, previewId, index) {
  2213 + var p1 = $.extend(self.getOutData({}, {}, files), {id: previewId, index: index}),
  2214 + p2 = {id: previewId, index: index, file: file, files: files};
  2215 + return self.isUploadable ? self.showUploadError(mesg, p1) : self.showError(mesg, p2);
  2216 + };
  2217 + self.reader = null;
  2218 + self.resetUpload();
  2219 + self.hideFileIcon();
  2220 + if (self.isUploadable) {
  2221 + self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
  2222 + }
  2223 + if (isDragDrop) {
  2224 + tfiles = [];
  2225 + while (files[i]) {
  2226 + f = files[i];
  2227 + if (!f.type && f.size % 4096 === 0) {
  2228 + folders++;
  2229 + } else {
  2230 + tfiles.push(f);
  2231 + }
  2232 + i++;
  2233 + }
  2234 + } else {
  2235 + if (e.target.files === undefined) {
  2236 + tfiles = e.target && e.target.value ? [
  2237 + {name: e.target.value.replace(/^.+\\/, '')}
  2238 + ] : [];
  2239 + } else {
  2240 + tfiles = e.target.files;
  2241 + }
  2242 + }
  2243 + if (isEmpty(tfiles) || tfiles.length === 0) {
  2244 + if (!isAjaxUpload) {
  2245 + self.clear();
  2246 + }
  2247 + self.showFolderError(folders);
  2248 + self.raise('fileselectnone');
  2249 + return;
  2250 + }
  2251 + self.resetErrors();
  2252 + len = tfiles.length;
  2253 + total = self.isUploadable ? self.getFileStack().length + len : len;
  2254 + total = self.getFileCount(total);
  2255 + if (self.maxFileCount > 0 && total > self.maxFileCount) {
  2256 + if (!self.autoReplace || len > self.maxFileCount) {
  2257 + n = (self.autoReplace && len > self.maxFileCount) ? len : total;
  2258 + msg = self.msgFilesTooMany.replace('{m}', self.maxFileCount).replace('{n}', n);
  2259 + self.isError = throwError(msg, null, null, null);
  2260 + self.$captionContainer.find('.kv-caption-icon').hide();
  2261 + self.setCaption('', true);
  2262 + self.$container.removeClass('file-input-new file-input-ajax-new');
  2263 + return;
  2264 + }
  2265 + if (total > self.maxFileCount) {
  2266 + self.resetPreviewThumbs(isAjaxUpload);
  2267 + }
  2268 + } else {
  2269 + if (!isAjaxUpload || flagSingle) {
  2270 + self.resetPreviewThumbs(false);
  2271 + if (flagSingle) {
  2272 + self.clearStack();
  2273 + }
  2274 + } else {
  2275 + if (isAjaxUpload && ctr === 0 && (!previewCache.count(self.id) || self.overwriteInitial)) {
  2276 + self.resetPreviewThumbs(true);
  2277 + }
  2278 + }
  2279 + }
  2280 + if (self.isPreviewable) {
  2281 + self.readFiles(tfiles);
  2282 + } else {
  2283 + self.updateFileDetails(1);
  2284 + }
  2285 + self.showFolderError(folders);
  2286 + },
  2287 + getFileName: function (file) {
  2288 + return file && file.name ? this.slug(file.name) : undefined;
  2289 + },
  2290 + getFileNames: function (skipNull) {
  2291 + var self = this;
  2292 + return self.filenames.filter(function (n) {
  2293 + return (skipNull ? n !== undefined : n !== undefined && n !== null);
  2294 + });
  2295 + },
  2296 + getFileStack: function (skipNull) {
  2297 + var self = this;
  2298 + return self.filestack.filter(function (n) {
  2299 + return (skipNull ? n !== undefined : n !== undefined && n !== null);
  2300 + });
  2301 + },
  2302 + clearStack: function () {
  2303 + var self = this;
  2304 + self.filestack = [];
  2305 + self.filenames = [];
  2306 + },
  2307 + updateStack: function (i, file) {
  2308 + var self = this;
  2309 + self.filestack[i] = file;
  2310 + self.filenames[i] = self.getFileName(file);
  2311 + },
  2312 + pushStack: function (file) {
  2313 + var self = this;
  2314 + self.filestack.push(file);
  2315 + self.filenames.push(self.getFileName(file));
  2316 + },
  2317 + checkDimensions: function (i, chk, $img, $thumb, fname, type, params) {
  2318 + var self = this, msg, dim, tag = chk === 'Small' ? 'min' : 'max',
  2319 + limit = self[tag + 'Image' + type], $imgEl, isValid;
  2320 + if (isEmpty(limit) || !$img.length) {
  2321 + return;
  2322 + }
  2323 + $imgEl = $img[0];
  2324 + dim = (type === 'Width') ? $imgEl.naturalWidth || $imgEl.width : $imgEl.naturalHeight || $imgEl.height;
  2325 + isValid = chk === 'Small' ? dim >= limit : dim <= limit;
  2326 + if (isValid) {
  2327 + return;
  2328 + }
  2329 + msg = self['msgImage' + type + chk].replace('{name}', fname).replace('{size}', limit);
  2330 + self.showUploadError(msg, params);
  2331 + self.setThumbStatus($thumb, 'Error');
  2332 + self.updateStack(i, null);
  2333 + },
  2334 + validateImage: function (i, previewId, fname, ftype) {
  2335 + var self = this, $preview = self.$preview, params, w1, w2,
  2336 + $thumb = $preview.find("#" + previewId), $img = $thumb.find('img');
  2337 + fname = fname || 'Untitled';
  2338 + if (!$img.length) {
  2339 + return;
  2340 + }
  2341 + handler($img, 'load', function () {
  2342 + w1 = $thumb.width();
  2343 + w2 = $preview.width();
  2344 + if (w1 > w2) {
  2345 + $img.css('width', '100%');
  2346 + $thumb.css('width', '97%');
  2347 + }
  2348 + params = {ind: i, id: previewId};
  2349 + self.checkDimensions(i, 'Small', $img, $thumb, fname, 'Width', params);
  2350 + self.checkDimensions(i, 'Small', $img, $thumb, fname, 'Height', params);
  2351 + if (!self.resizeImage) {
  2352 + self.checkDimensions(i, 'Large', $img, $thumb, fname, 'Width', params);
  2353 + self.checkDimensions(i, 'Large', $img, $thumb, fname, 'Height', params);
  2354 + }
  2355 + self.raise('fileimageloaded', [previewId]);
  2356 + self.loadedImages.push({ind: i, img: $img, thumb: $thumb, pid: previewId, typ: ftype});
  2357 + self.validateAllImages();
  2358 + objUrl.revokeObjectURL($img.attr('src'));
  2359 + });
  2360 + },
  2361 + validateAllImages: function () {
  2362 + var self = this, i, config, $img, $thumb, pid, ind, params = {}, errFunc;
  2363 + if (self.loadedImages.length !== self.totalImagesCount) {
  2364 + return;
  2365 + }
  2366 + self.raise('fileimagesloaded');
  2367 + if (!self.resizeImage) {
  2368 + return;
  2369 + }
  2370 + errFunc = self.isUploadable ? self.showUploadError : self.showError;
  2371 + for (i = 0; i < self.loadedImages.length; i++) {
  2372 + config = self.loadedImages[i];
  2373 + $img = config.img;
  2374 + $thumb = config.thumb;
  2375 + pid = config.pid;
  2376 + ind = config.ind;
  2377 + params = {id: pid, 'index': ind};
  2378 + if (!self.getResizedImage($img[0], config.typ, pid, ind)) {
  2379 + errFunc(self.msgImageResizeError, params, 'fileimageresizeerror');
  2380 + self.setThumbStatus($thumb, 'Error');
  2381 + self.updateStack(ind, undefined);
  2382 + }
  2383 + }
  2384 + self.raise('fileimagesresized');
  2385 + },
  2386 + getResizedImage: function (image, type, pid, ind) {
  2387 + var self = this, width = image.naturalWidth, height = image.naturalHeight, ratio = 1,
  2388 + maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
  2389 + isValidImage = (width && height), chkWidth, chkHeight,
  2390 + canvas = self.imageCanvas, context = self.imageCanvasContext;
  2391 + if (!isValidImage) {
  2392 + return false;
  2393 + }
  2394 + if (width === maxWidth && height === maxHeight) {
  2395 + return true;
  2396 + }
  2397 + type = type || self.resizeDefaultImageType;
  2398 + chkWidth = width > maxWidth;
  2399 + chkHeight = height > maxHeight;
  2400 + if (self.resizePreference === 'width') {
  2401 + ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
  2402 + } else {
  2403 + ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
  2404 + }
  2405 + self.resetCanvas();
  2406 + width *= ratio;
  2407 + height *= ratio;
  2408 + canvas.width = width;
  2409 + canvas.height = height;
  2410 + try {
  2411 + context.drawImage(image, 0, 0, width, height);
  2412 + canvas.toBlob(function (blob) {
  2413 + self.raise('fileimageresized', [pid, ind]);
  2414 + self.filestack[ind] = blob;
  2415 + }, type, self.resizeQuality);
  2416 + return true;
  2417 + }
  2418 + catch (err) {
  2419 + return false;
  2420 + }
  2421 + },
  2422 + initCaption: function () {
  2423 + var self = this, cap = self.initialCaption || '';
  2424 + if (self.overwriteInitial || isEmpty(cap)) {
  2425 + self.$caption.html('');
  2426 + return false;
  2427 + }
  2428 + self.setCaption(cap);
  2429 + return true;
  2430 + },
  2431 + setCaption: function (content, isError) {
  2432 + var self = this, title, out;
  2433 + if (isError) {
  2434 + title = $('<div>' + self.msgValidationError + '</div>').text();
  2435 + out = '<span class="' + self.msgValidationErrorClass + '">' +
  2436 + self.msgValidationErrorIcon + title + '</span>';
  2437 + } else {
  2438 + if (isEmpty(content) || self.$caption.length === 0) {
  2439 + return;
  2440 + }
  2441 + title = $('<div>' + content + '</div>').text();
  2442 + out = self.getLayoutTemplate('icon') + title;
  2443 + }
  2444 + self.$caption.html(out);
  2445 + self.$caption.attr('title', title);
  2446 + self.$captionContainer.find('.file-caption-ellipsis').attr('title', title);
  2447 + },
  2448 + initBrowse: function ($container) {
  2449 + var self = this;
  2450 + self.$btnFile = $container.find('.btn-file');
  2451 + self.$btnFile.append(self.$element);
  2452 + },
  2453 + createContainer: function () {
  2454 + var self = this,
  2455 + $container = $(document.createElement("div"))
  2456 + .attr({"class": 'file-input file-input-new'})
  2457 + .html(self.renderMain());
  2458 + self.$element.before($container);
  2459 + self.initBrowse($container);
  2460 + return $container;
  2461 + },
  2462 + refreshContainer: function () {
  2463 + var self = this, $container = self.$container;
  2464 + $container.before(self.$element);
  2465 + $container.html(self.renderMain());
  2466 + self.initBrowse($container);
  2467 + },
  2468 + renderMain: function () {
  2469 + var self = this, dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : 'file-drop-disabled',
  2470 + close = !self.showClose ? '' : self.getLayoutTemplate('close'),
  2471 + preview = !self.showPreview ? '' : self.getLayoutTemplate('preview')
  2472 + .replace(/\{class}/g, self.previewClass)
  2473 + .replace(/\{dropClass}/g, dropCss),
  2474 + css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
  2475 + caption = self.captionTemplate.replace(/\{class}/g, css + ' kv-fileinput-caption');
  2476 + return self.mainTemplate.replace(/\{class}/g, self.mainClass)
  2477 + .replace(/\{preview}/g, preview)
  2478 + .replace(/\{close}/g, close)
  2479 + .replace(/\{caption}/g, caption)
  2480 + .replace(/\{upload}/g, self.renderButton('upload'))
  2481 + .replace(/\{remove}/g, self.renderButton('remove'))
  2482 + .replace(/\{cancel}/g, self.renderButton('cancel'))
  2483 + .replace(/\{browse}/g, self.renderButton('browse'));
  2484 + },
  2485 + renderButton: function (type) {
  2486 + var self = this, tmplt = self.getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
  2487 + title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
  2488 + status = self.isDisabled ? ' disabled' : '', btnType = 'button';
  2489 + switch (type) {
  2490 + case 'remove':
  2491 + if (!self.showRemove) {
  2492 + return '';
  2493 + }
  2494 + break;
  2495 + case 'cancel':
  2496 + if (!self.showCancel) {
  2497 + return '';
  2498 + }
  2499 + css += ' hide';
  2500 + break;
  2501 + case 'upload':
  2502 + if (!self.showUpload) {
  2503 + return '';
  2504 + }
  2505 + if (self.isUploadable && !self.isDisabled) {
  2506 + tmplt = self.getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
  2507 + } else {
  2508 + btnType = 'submit';
  2509 + }
  2510 + break;
  2511 + case 'browse':
  2512 + tmplt = self.getLayoutTemplate('btnBrowse');
  2513 + break;
  2514 + default:
  2515 + return '';
  2516 + }
  2517 + css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
  2518 + if (!isEmpty(label)) {
  2519 + label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
  2520 + }
  2521 + return tmplt.replace('{type}', btnType)
  2522 + .replace('{css}', css)
  2523 + .replace('{title}', title)
  2524 + .replace('{status}', status)
  2525 + .replace('{icon}', icon)
  2526 + .replace('{label}', label);
  2527 + }
  2528 + };
  2529 +
  2530 + $.fn.fileinput = function (option) {
  2531 + if (!hasFileAPISupport() && !isIE(9)) {
  2532 + return;
  2533 + }
  2534 + var args = Array.apply(null, arguments), retvals = [];
  2535 + args.shift();
  2536 + this.each(function () {
  2537 + var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
  2538 + lang = options.language || self.data('language') || 'en', config = $.fn.fileinput.defaults;
  2539 +
  2540 + if (!data) {
  2541 + if (lang !== 'en' && !isEmpty($.fn.fileinputLocales[lang])) {
  2542 + $.extend(config, $.fn.fileinputLocales[lang]);
  2543 + }
  2544 + data = new FileInput(this, $.extend(config, options, self.data()));
  2545 + self.data('fileinput', data);
  2546 + }
  2547 +
  2548 + if (typeof option === 'string') {
  2549 + retvals.push(data[option].apply(data, args));
  2550 + }
  2551 + });
  2552 + switch (retvals.length) {
  2553 + case 0:
  2554 + return this;
  2555 + case 1:
  2556 + return retvals[0];
  2557 + default:
  2558 + return retvals;
  2559 + }
  2560 + };
  2561 +
  2562 + $.fn.fileinput.defaults = {
  2563 + language: 'en',
  2564 + showCaption: true,
  2565 + showPreview: true,
  2566 + showRemove: true,
  2567 + showUpload: true,
  2568 + showCancel: true,
  2569 + showClose: true,
  2570 + showUploadedThumbs: true,
  2571 + autoReplace: false,
  2572 + mainClass: '',
  2573 + previewClass: '',
  2574 + captionClass: '',
  2575 + mainTemplate: null,
  2576 + initialCaption: '',
  2577 + initialPreview: [],
  2578 + initialPreviewDelimiter: '*$$*',
  2579 + initialPreviewConfig: [],
  2580 + initialPreviewThumbTags: [],
  2581 + previewThumbTags: {},
  2582 + initialPreviewShowDelete: true,
  2583 + deleteUrl: '',
  2584 + deleteExtraData: {},
  2585 + overwriteInitial: true,
  2586 + layoutTemplates: defaultLayoutTemplates,
  2587 + previewTemplates: defaultPreviewTemplates,
  2588 + allowedPreviewTypes: defaultPreviewTypes,
  2589 + allowedPreviewMimeTypes: null,
  2590 + allowedFileTypes: null,
  2591 + allowedFileExtensions: null,
  2592 + defaultPreviewContent: null,
  2593 + customLayoutTags: {},
  2594 + customPreviewTags: {},
  2595 + previewSettings: defaultPreviewSettings,
  2596 + fileTypeSettings: defaultFileTypeSettings,
  2597 + previewFileIcon: '<i class="glyphicon glyphicon-file"></i>',
  2598 + previewFileIconClass: 'file-icon-4x',
  2599 + previewFileIconSettings: {},
  2600 + previewFileExtSettings: {},
  2601 + buttonLabelClass: 'hidden-xs',
  2602 + browseIcon: '<i class="glyphicon glyphicon-folder-open"></i>',
  2603 + browseClass: 'btn btn-primary',
  2604 + removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
  2605 + removeClass: 'btn btn-default',
  2606 + cancelIcon: '<i class="glyphicon glyphicon-ban-circle"></i>',
  2607 + cancelClass: 'btn btn-default',
  2608 + uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
  2609 + uploadClass: 'btn btn-default',
  2610 + uploadUrl: null,
  2611 + uploadAsync: true,
  2612 + uploadExtraData: {},
  2613 + minImageWidth: null,
  2614 + minImageHeight: null,
  2615 + maxImageWidth: null,
  2616 + maxImageHeight: null,
  2617 + resizeImage: false,
  2618 + resizePreference: 'width',
  2619 + resizeQuality: 0.92,
  2620 + resizeDefaultImageType: 'image/jpeg',
  2621 + maxFileSize: 0,
  2622 + minFileCount: 0,
  2623 + maxFileCount: 0,
  2624 + validateInitialCount: false,
  2625 + msgValidationErrorClass: 'text-danger',
  2626 + msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
  2627 + msgErrorClass: 'file-error-message',
  2628 + progressThumbClass: "progress-bar progress-bar-success progress-bar-striped active",
  2629 + progressClass: "progress-bar progress-bar-success progress-bar-striped active",
  2630 + progressCompleteClass: "progress-bar progress-bar-success",
  2631 + previewFileType: 'image',
  2632 + zoomIndicator: '<i class="glyphicon glyphicon-zoom-in"></i>',
  2633 + elCaptionContainer: null,
  2634 + elCaptionText: null,
  2635 + elPreviewContainer: null,
  2636 + elPreviewImage: null,
  2637 + elPreviewStatus: null,
  2638 + elErrorContainer: null,
  2639 + errorCloseButton: '<span class="close kv-error-close">&times;</span>',
  2640 + slugCallback: null,
  2641 + dropZoneEnabled: true,
  2642 + dropZoneTitleClass: 'file-drop-zone-title',
  2643 + fileActionSettings: {},
  2644 + otherActionButtons: '',
  2645 + textEncoding: 'UTF-8',
  2646 + ajaxSettings: {},
  2647 + ajaxDeleteSettings: {},
  2648 + showAjaxErrorDetails: true
  2649 + };
  2650 +
  2651 + $.fn.fileinputLocales.en = {
  2652 + fileSingle: 'file',
  2653 + filePlural: 'files',
  2654 + browseLabel: 'Browse &hellip;',
  2655 + removeLabel: 'Remove',
  2656 + removeTitle: 'Clear selected files',
  2657 + cancelLabel: 'Cancel',
  2658 + cancelTitle: 'Abort ongoing upload',
  2659 + uploadLabel: 'Upload',
  2660 + uploadTitle: 'Upload selected files',
  2661 + msgZoomTitle: 'View details',
  2662 + msgZoomModalHeading: 'Detailed Preview',
  2663 + msgSizeTooLarge: 'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',
  2664 + msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
  2665 + msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
  2666 + msgFileNotFound: 'File "{name}" not found!',
  2667 + msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
  2668 + msgFileNotReadable: 'File "{name}" is not readable.',
  2669 + msgFilePreviewAborted: 'File preview aborted for "{name}".',
  2670 + msgFilePreviewError: 'An error occurred while reading the file "{name}".',
  2671 + msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
  2672 + msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
  2673 + msgUploadAborted: 'The file upload was aborted',
  2674 + msgValidationError: 'File Upload Error',
  2675 + msgLoading: 'Loading file {index} of {files} &hellip;',
  2676 + msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
  2677 + msgSelected: '{n} {files} selected',
  2678 + msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
  2679 + msgImageWidthSmall: 'Width of image file "{name}" must be at least {size} px.',
  2680 + msgImageHeightSmall: 'Height of image file "{name}" must be at least {size} px.',
  2681 + msgImageWidthLarge: 'Width of image file "{name}" cannot exceed {size} px.',
  2682 + msgImageHeightLarge: 'Height of image file "{name}" cannot exceed {size} px.',
  2683 + msgImageResizeError: 'Could not get the image dimensions to resize.',
  2684 + msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
  2685 + dropZoneTitle: 'Drag & drop files here &hellip;'
  2686 + };
  2687 +
  2688 + $.extend($.fn.fileinput.defaults, $.fn.fileinputLocales.en);
  2689 +
  2690 + $.fn.fileinput.Constructor = FileInput;
  2691 +
  2692 + /**
  2693 + * Convert automatically file inputs with class 'file'
  2694 + * into a bootstrap fileinput control.
  2695 + */
  2696 + $(document).ready(function () {
  2697 + var $input = $('input.file[type=file]');
  2698 + if ($input.length) {
  2699 + $input.fileinput();
  2700 + }
  2701 + });
  2702 +}));
0 2703 \ No newline at end of file
... ...
src/main/webapp/static/assets/plugins/fileinput/fileinput.min.css 0 → 100644
  1 +/*!
  2 + * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014 - 2015
  3 + * @package bootstrap-fileinput
  4 + * @version 4.2.9
  5 + *
  6 + * File input styling for Bootstrap 3.0
  7 + * Built for Yii Framework 2.0
  8 + * Author: Kartik Visweswaran
  9 + * Year: 2015
  10 + * For more Yii related demos visit http://demos.krajee.com
  11 + */.file-preview-frame,.file-preview-image,.file-preview-other{height:160px;vertical-align:middle}.file-loading{top:0;right:0;width:25px;height:25px;font-size:999px;text-align:right;color:#fff;background:url(../img/loading.gif)top left no-repeat;border:none}.file-object{margin:0 0 -5px;padding:0}.btn-file{position:relative;overflow:hidden}.btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;text-align:right;opacity:0;background:0 0;cursor:inherit;display:block}.file-caption-name{display:inline-block;overflow:hidden;height:20px;word-break:break-all}.input-group-lg .file-caption-name{height:25px}.file-preview-detail-modal{text-align:left}.file-error-message{color:#a94442;background-color:#f2dede;margin:5px;border:1px solid #ebccd1;border-radius:4px;padding:15px}.file-error-message pre,.file-error-message ul{margin:0;text-align:left}.file-error-message pre{margin:5px 0}.file-caption-disabled{background-color:#EEE;cursor:not-allowed;opacity:1}.file-preview{border-radius:5px;border:1px solid #ddd;padding:5px;width:100%;margin-bottom:5px}.file-preview-frame{display:table;margin:8px;border:1px solid #ddd;box-shadow:1px 1px 5px 0 #a2958a;padding:6px;float:left;text-align:center}.file-preview-frame:not(.file-preview-error):hover{box-shadow:3px 3px 5px 0 #333}.file-preview-text{text-align:left;width:160px;margin-bottom:2px;color:#428bca;background:#fff;overflow-x:hidden}.file-preview-other{display:table-cell;text-align:center;width:160px;border:2px solid #999;border-radius:30px}.file-preview-other:hover{opacity:.8}.file-actions,.file-other-error{text-align:left}.file-icon-lg{font-size:1.2em}.file-icon-2x{font-size:2.4em}.file-icon-4x{font-size:4.8em}.file-input-ajax-new .fileinput-remove-button,.file-input-ajax-new .fileinput-upload-button,.file-input-new .close,.file-input-new .file-preview,.file-input-new .fileinput-remove-button,.file-input-new .fileinput-upload-button,.file-input-new .glyphicon-file{display:none}.file-thumb-loading{background:url(../img/loading.gif)center center no-repeat content-box!important}.file-actions{margin-top:15px}.file-footer-buttons{float:right}.file-upload-indicator{padding-top:2px;cursor:default;opacity:.8;width:60%}.file-upload-indicator:hover{font-weight:700;opacity:1}.file-footer-caption{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:160px;text-align:center;padding-top:4px;font-size:11px;color:#777;margin:5px auto 10px}.file-preview-error{opacity:.65;box-shadow:none}.file-preview-frame:not(.file-preview-error) .file-footer-caption:hover{color:#000}.file-drop-zone{border:1px dashed #aaa;border-radius:4px;height:100%;text-align:center;vertical-align:middle;margin:12px 15px 12px 12px;padding:5px}.file-drop-zone-title{color:#aaa;font-size:40px;padding:85px 10px}.file-highlighted{border:2px dashed #999!important;background-color:#f0f0f0}.file-uploading{background:url(../img/loading-sm.gif)center bottom 10px no-repeat;opacity:.65}.file-thumb-progress .progress,.file-thumb-progress .progress-bar{height:10px;font-size:9px;line-height:10px}.file-thumbnail-footer{position:relative}.file-thumb-progress{position:absolute;top:22px;left:0;right:0}.btn-file ::-ms-browse{width:100%;height:100%}
0 12 \ No newline at end of file
... ...
src/main/webapp/static/assets/plugins/fileinput/fileinput.min.js 0 → 100644
  1 +/*!
  2 + * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014 - 2015
  3 + * @version 4.2.9
  4 + *
  5 + * File input styled for Bootstrap 3.0 that utilizes HTML5 File Input's advanced
  6 + * features including the FileReader API.
  7 + *
  8 + * The plugin drastically enhances the HTML file input to preview multiple files on the client before
  9 + * upload. In addition it provides the ability to preview content of images, text, videos, audio, html,
  10 + * flash and other objects. It also offers the ability to upload and delete files using AJAX, and add
  11 + * files in batches (i.e. preview, append, or remove before upload).
  12 + *
  13 + * Author: Kartik Visweswaran
  14 + * Copyright: 2015, Kartik Visweswaran, Krajee.com
  15 + * For more JQuery plugins visit http://plugins.krajee.com
  16 + * For more Yii related demos visit http://demos.krajee.com
  17 + */!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=e(require("jquery")):e(window.jQuery)}(function(e){"use strict";e.fn.fileinputLocales={};var i,t,a,r,n,l,o,s,d,c,p,u,f,v,g,m,h,w,b,C,x,y,T,F,I,E,k,S,$,P,D,U,A,j,L,z,O,R,M,B,N,Z,H,W,q,_,V,K,X,J,Q,Y;i=function(e){if("Microsoft Internet Explorer"!==navigator.appName)return!1;if(10===e)return new RegExp("msie\\s"+e,"i").test(navigator.userAgent);var i,t=document.createElement("div");return t.innerHTML="<!--[if IE "+e+"]> <i></i> <![endif]-->",i=t.getElementsByTagName("i").length,document.body.appendChild(t),t.parentNode.removeChild(t),i},t=function(){return new RegExp("Edge/[0-9]+","i").test(navigator.userAgent)},a=function(e,i,t,a){var r=a?i:i+".fileinput";e.off(r).on(r,t)},r={data:{},init:function(e){var i=e.initialPreview,t=e.id;i.length>0&&!q(i)&&(i=i.split(e.initialPreviewDelimiter)),r.data[t]={content:i,config:e.initialPreviewConfig,tags:e.initialPreviewThumbTags,delimiter:e.initialPreviewDelimiter,template:e.previewGenericTemplate,msg:function(i){return e.getMsgSelected(i)},initId:e.previewInitId,footer:e.getLayoutTemplate("footer").replace(/\{progress}/g,e.renderThumbProgress()),isDelete:e.initialPreviewShowDelete,caption:e.initialCaption,actions:function(i,t,a,r,n){return e.renderFileActions(i,t,a,r,n)}}},fetch:function(e){return r.data[e].content.filter(function(e){return null!==e})},count:function(e,i){return r.data[e]&&r.data[e].content?i?r.data[e].content.length:r.fetch(e).length:0},get:function(i,t,a){var n,l,o="init_"+t,s=r.data[i],d=s.config[t],c=s.initId+"-"+o,p=" file-preview-initial";return a=void 0===a?!0:a,null===s.content[t]?"":(W(d)||W(d.frameClass)||(p+=" "+d.frameClass),n=s.template.replace(/\{previewId}/g,c).replace(/\{frameClass}/g,p).replace(/\{fileindex}/g,o).replace(/\{content}/g,s.content[t]).replace(/\{footer}/g,r.footer(i,t,a)),s.tags.length&&s.tags[t]&&(n=J(n,s.tags[t])),W(d)||W(d.frameAttr)||(l=e(document.createElement("div")).html(n),l.find(".file-preview-initial").attr(d.frameAttr),n=l.html(),l.remove()),n)},add:function(i,t,a,n,l){var o,s=e.extend(!0,{},r.data[i]);return q(t)||(t=t.split(s.delimiter)),l?(o=s.content.push(t)-1,s.config[o]=a,s.tags[o]=n):(o=t.length,s.content=t,s.config=a,s.tags=n),r.data[i]=s,o},set:function(i,t,a,n,l){var o,s,d=e.extend(!0,{},r.data[i]);if(t&&t.length&&(q(t)||(t=t.split(d.delimiter)),s=t.filter(function(e){return null!==e}),s.length)){if(void 0===d.content&&(d.content=[]),void 0===d.config&&(d.config=[]),void 0===d.tags&&(d.tags=[]),l){for(o=0;o<t.length;o++)t[o]&&d.content.push(t[o]);for(o=0;o<a.length;o++)a[o]&&d.config.push(a[o]);for(o=0;o<n.length;o++)n[o]&&d.tags.push(n[o])}else d.content=t,d.config=a,d.tags=n;r.data[i]=d}},unset:function(e,i){var t=r.count(e);if(t){if(1===t)return r.data[e].content=[],void(r.data[e].config=[]);r.data[e].content[i]=null,r.data[e].config[i]=null}},out:function(e){var i,t="",a=r.data[e],n=r.count(e,!0);if(0===n)return{content:"",caption:""};for(var l=0;n>l;l++)t+=r.get(e,l);return i=a.msg(r.count(e)),{content:t,caption:i}},footer:function(e,i,t){var a=r.data[e];if(t=void 0===t?!0:t,0===a.config.length||W(a.config[i]))return"";var n=a.config[i],l=_("caption",n)?n.caption:"",o=_("width",n)?n.width:"auto",s=_("url",n)?n.url:!1,d=_("key",n)?n.key:null,c=s===!1&&t,p=a.isDelete?a.actions(!1,!0,c,s,d):"",u=a.footer.replace(/\{actions}/g,p);return u.replace(/\{caption}/g,l).replace(/\{width}/g,o).replace(/\{indicator}/g,"").replace(/\{indicatorTitle}/g,"")}},n=function(e,i){return i=i||0,"number"==typeof e?e:("string"==typeof e&&(e=parseFloat(e)),isNaN(e)?i:e)},l=function(){return window.File&&window.FileReader},o=function(){var e=document.createElement("div");return!i(9)&&!t()&&(void 0!==e.draggable||void 0!==e.ondragstart&&void 0!==e.ondrop)},s=function(){return l()&&window.FormData},d=function(e,i){e.removeClass(i).addClass(i)},c='style="width:{width};height:{height};"',p=' <param name="controller" value="true" />\n <param name="allowFullScreen" value="true" />\n <param name="allowScriptAccess" value="always" />\n <param name="autoPlay" value="false" />\n <param name="autoStart" value="false" />\n <param name="quality" value="high" />\n',u='<div class="file-preview-other">\n <span class="{previewFileIconClass}">{previewFileIcon}</span>\n</div>',f={removeIcon:'<i class="glyphicon glyphicon-trash text-danger"></i>',removeClass:"btn btn-xs btn-default",removeTitle:"Remove file",uploadIcon:'<i class="glyphicon glyphicon-upload text-info"></i>',uploadClass:"btn btn-xs btn-default",uploadTitle:"Upload file",indicatorNew:'<i class="glyphicon glyphicon-hand-down text-warning"></i>',indicatorSuccess:'<i class="glyphicon glyphicon-ok-sign text-success"></i>',indicatorError:'<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',indicatorLoading:'<i class="glyphicon glyphicon-hand-up text-muted"></i>',indicatorNewTitle:"Not uploaded yet",indicatorSuccessTitle:"Uploaded",indicatorErrorTitle:"Upload Error",indicatorLoadingTitle:"Uploading ..."},v='{preview}\n<div class="kv-upload-progress hide"></div>\n<div class="input-group {class}">\n {caption}\n <div class="input-group-btn">\n {remove}\n {cancel}\n {upload}\n {browse}\n </div>\n</div>',g='{preview}\n<div class="kv-upload-progress hide"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n',m='<div class="file-preview {class}">\n {close} <div class="{dropClass}">\n <div class="file-preview-thumbnails">\n </div>\n <div class="clearfix"></div> <div class="file-preview-status text-center text-success"></div>\n <div class="kv-fileinput-error"></div>\n </div>\n</div>',w='<div class="close fileinput-remove">&times;</div>\n',h='<span class="glyphicon glyphicon-file kv-caption-icon"></span>',b='<div tabindex="500" class="form-control file-caption {class}">\n <div class="file-caption-name"></div>\n</div>\n',C='<button type="{type}" tabindex="500" title="{title}" class="{css}" {status}>{icon}{label}</button>',x='<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon}{label}</a>',y='<div tabindex="500" class="{css}" {status}>{icon}{label}</div>',T='<div id="{id}" class="file-preview-detail-modal modal fade" tabindex="-1">\n <div class="modal-dialog modal-lg">\n <div class="modal-content">\n <div class="modal-header">\n <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>\n <h3 class="modal-title">{heading} <small>{title}</small></h3>\n </div>\n <div class="modal-body">\n <pre>{body}</pre>\n </div>\n </div>\n </div>\n</div>',F='<div class="progress">\n <div class="{class}" role="progressbar" aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n {percent}%\n </div>\n</div>',I='<div class="file-thumbnail-footer">\n <div class="file-footer-caption" title="{caption}">{caption}</div>\n {progress} {actions}\n</div>',E='<div class="file-actions">\n <div class="file-footer-buttons">\n {upload}{delete}{other} </div>\n <div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>\n <div class="clearfix"></div>\n</div>',k='<button type="button" class="kv-file-remove {removeClass}" title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n',S='<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}"> {uploadIcon}\n</button>\n',$='<button type="button" class="btn btn-default btn-xs btn-block" title="{zoomTitle}: {caption}" onclick="{dialog}">\n {zoomInd}\n</button>\n',P='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n {content}\n {footer}\n</div>\n',D='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n <object class="file-object" data="{data}" type="{type}" width="{width}" height="{height}">\n '+u+"\n </object>\n {footer}\n</div>",U='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n <img src="{data}" class="file-preview-image" title="{caption}" alt="{caption}" '+c+">\n {footer}\n</div>\n",A='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}">\n <pre class="file-preview-text" title="{caption}" '+c+">{data}</pre>\n {zoom}\n {footer}\n</div>",j='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}" title="{caption}" '+c+'>\n <video width="{width}" height="{height}" controls>\n <source src="{data}" type="{type}">\n '+u+"\n </video>\n {footer}\n</div>\n",L='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}" title="{caption}" '+c+'>\n <audio controls>\n <source src="{data}" type="{type}">\n '+u+"\n </audio>\n {footer}\n</div>",z='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}" title="{caption}" '+c+'>\n <object class="file-object" type="application/x-shockwave-flash" width="{width}" height="{height}" data="{data}">\n'+p+" "+u+"\n </object>\n {footer}\n</div>\n",O='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}" title="{caption}" '+c+'>\n <object class="file-object" data="{data}" type="{type}" width="{width}" height="{height}">\n <param name="movie" value="{caption}" />\n'+p+" "+u+"\n </object>\n {footer}\n</div>",R='<div class="file-preview-frame{frameClass}" id="{previewId}" data-fileindex="{fileindex}" title="{caption}" '+c+'>\n <div class="file-preview-other-frame">\n '+u+'\n </div>\n <div class="file-preview-other-footer">{footer}</div>\n</div>',M={main1:v,main2:g,preview:m,close:w,zoom:$,icon:h,caption:b,modal:T,progress:F,footer:I,actions:E,actionDelete:k,actionUpload:S,btnDefault:C,btnLink:x,btnBrowse:y},B={generic:P,html:D,image:U,text:A,video:j,audio:L,flash:z,object:O,other:R},N=["image","html","text","video","audio","flash","object"],Z={image:{width:"auto",height:"160px"},html:{width:"213px",height:"160px"},text:{width:"160px",height:"136px"},video:{width:"213px",height:"160px"},audio:{width:"213px",height:"80px"},flash:{width:"213px",height:"160px"},object:{width:"160px",height:"160px"},other:{width:"160px",height:"160px"}},H={image:function(e,i){return void 0!==e?e.match("image.*"):i.match(/\.(gif|png|jpe?g)$/i)},html:function(e,i){return void 0!==e?"text/html"===e:i.match(/\.(htm|html)$/i)},text:function(e,i){return void 0!==e&&e.match("text.*")||i.match(/\.(txt|md|csv|nfo|ini|json|php|js|css)$/i)},video:function(e,i){return void 0!==e&&e.match(/\.video\/(ogg|mp4|webm|3gp)$/i)||i.match(/\.(og?|mp4|webm|3gp)$/i)},audio:function(e,i){return void 0!==e&&e.match(/\.audio\/(ogg|mp3|wav)$/i)||i.match(/\.(ogg|mp3|wav)$/i)},flash:function(e,i){return void 0!==e&&"application/x-shockwave-flash"===e||i.match(/\.(swf)$/i)},object:function(){return!0},other:function(){return!0}},W=function(i,t){return void 0===i||null===i||0===i.length||t&&""===e.trim(i)},q=function(e){return Array.isArray(e)||"[object Array]"===Object.prototype.toString.call(e)},_=function(e,i){return"object"==typeof i&&e in i},V=function(i,t,a){return W(i)||W(i[t])?a:e(i[t])},K=function(){return Math.round((new Date).getTime()+100*Math.random())},X=function(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")},J=function(i,t){var a=i;return t?(e.each(t,function(e,i){"function"==typeof i&&(i=i()),a=a.split(e).join(i)}),a):a},Q=window.URL||window.webkitURL,Y=function(t,a){var r=this;r.$element=e(t),r.validate()&&(r.isPreviewable=l(),r.isIE9=i(9),r.isIE10=i(10),r.isPreviewable||r.isIE9?(r.init(a),r.listen()):r.$element.removeClass("file-loading"))},Y.prototype={constructor:Y,validate:function(){var e,i=this;return"file"===i.$element.attr("type")?!0:(e='<div class="help-block alert alert-warning"><h4>Invalid Input Type</h4>You must set an input <code>type = file</code> for <b>bootstrap-fileinput</b> plugin to initialize.</div>',i.$element.after(e),!1)},init:function(i){var t,a=this,l=a.$element;e.each(i,function(e,i){switch(e){case"minFileCount":case"maxFileCount":case"maxFileSize":a[e]=n(i);break;default:a[e]=i}}),a.fileInputCleared=!1,a.fileBatchCompleted=!0,a.isPreviewable||(a.showPreview=!1),a.uploadFileAttr=W(l.attr("name"))?"file_data":l.attr("name"),a.reader=null,a.formdata={},a.clearStack(),a.uploadCount=0,a.uploadStatus={},a.uploadLog=[],a.uploadAsyncCount=0,a.loadedImages=[],a.totalImagesCount=0,a.ajaxRequests=[],a.isError=!1,a.ajaxAborted=!1,a.cancelling=!1,t=a.getLayoutTemplate("progress"),a.progressTemplate=t.replace("{class}",a.progressClass),a.progressCompleteTemplate=t.replace("{class}",a.progressCompleteClass),a.dropZoneEnabled=o()&&a.dropZoneEnabled,a.isDisabled=a.$element.attr("disabled")||a.$element.attr("readonly"),a.isUploadable=s()&&!W(a.uploadUrl),a.slug="function"==typeof i.slugCallback?i.slugCallback:a.slugDefault,a.mainTemplate=a.getLayoutTemplate(a.showCaption?"main1":"main2"),a.captionTemplate=a.getLayoutTemplate("caption"),a.previewGenericTemplate=a.getPreviewTemplate("generic"),a.resizeImage&&(a.maxImageWidth||a.maxImageHeight)&&(a.imageCanvas=document.createElement("canvas"),a.imageCanvasContext=a.imageCanvas.getContext("2d")),W(a.$element.attr("id"))&&a.$element.attr("id",K()),void 0===a.$container?a.$container=a.createContainer():a.refreshContainer(),a.$progress=a.$container.find(".kv-upload-progress"),a.$btnUpload=a.$container.find(".fileinput-upload"),a.$captionContainer=V(i,"elCaptionContainer",a.$container.find(".file-caption")),a.$caption=V(i,"elCaptionText",a.$container.find(".file-caption-name")),a.$previewContainer=V(i,"elPreviewContainer",a.$container.find(".file-preview")),a.$preview=V(i,"elPreviewImage",a.$container.find(".file-preview-thumbnails")),a.$previewStatus=V(i,"elPreviewStatus",a.$container.find(".file-preview-status")),a.$errorContainer=V(i,"elErrorContainer",a.$previewContainer.find(".kv-fileinput-error")),W(a.msgErrorClass)||d(a.$errorContainer,a.msgErrorClass),a.$errorContainer.hide(),a.fileActionSettings=e.extend(f,i.fileActionSettings),a.previewInitId="preview-"+K(),a.id=a.$element.attr("id"),r.init(a),a.initPreview(!0),a.initPreviewDeletes(),a.options=i,a.setFileDropZoneTitle(),a.$element.removeClass("file-loading"),a.$element.attr("disabled")&&a.disable()},parseError:function(i,t,a){var r=this,n=e.trim(t+""),l="."===n.slice(-1)?"":".",o=void 0!==i.responseJSON&&void 0!==i.responseJSON.error?i.responseJSON.error:i.responseText;return r.cancelling&&r.msgUploadAborted&&(n=r.msgUploadAborted),r.showAjaxErrorDetails&&o?(o=e.trim(o.replace(/\n\s*\n/g,"\n")),o=o.length>0?"<pre>"+o+"</pre>":"",n+=l+o):n+=l,r.cancelling=!1,a?"<b>"+a+": </b>"+n:n},raise:function(i,t){var a=this,r=e.Event(i);if(void 0!==t?a.$element.trigger(r,t):a.$element.trigger(r),r.isDefaultPrevented())return!1;if(!r.result)return r.result;switch(i){case"filebatchuploadcomplete":case"filebatchuploadsuccess":case"fileuploaded":case"fileclear":case"filecleared":case"filereset":case"fileerror":case"filefoldererror":case"fileuploaderror":case"filebatchuploaderror":case"filedeleteerror":case"filecustomerror":case"filesuccessremove":break;default:a.ajaxAborted=r.result}return!0},getLayoutTemplate:function(e){var i=this,t=_(e,i.layoutTemplates)?i.layoutTemplates[e]:M[e];return W(i.customLayoutTags)?t:J(t,i.customLayoutTags)},getPreviewTemplate:function(e){var i=this,t=_(e,i.previewTemplates)?i.previewTemplates[e]:B[e];return W(i.customPreviewTags)?t:J(t,i.customPreviewTags)},parseFilePreviewIcon:function(i,t){var a,r=this,n=r.previewFileIcon;return t&&t.indexOf(".")>-1&&(a=t.split(".").pop(),r.previewFileIconSettings&&r.previewFileIconSettings[a]&&(n=r.previewFileIconSettings[a]),r.previewFileExtSettings&&e.each(r.previewFileExtSettings,function(e,i){r.previewFileIconSettings[e]&&i(a)&&(n=r.previewFileIconSettings[e])})),i.indexOf("{previewFileIcon}")>-1?i.replace(/\{previewFileIconClass}/g,r.previewFileIconClass).replace(/\{previewFileIcon}/g,n):i},getOutData:function(e,i,t){var a=this;return e=e||{},i=i||{},t=t||a.filestack.slice(0)||{},{form:a.formdata,files:t,filenames:a.filenames,extra:a.getExtraData(),response:i,reader:a.reader,jqXHR:e}},listen:function(){var i=this,t=i.$element,r=i.$captionContainer,n=i.$btnFile,l=t.closest("form"),o=i.$container;a(t,"change",e.proxy(i.change,i)),a(n,"click",function(){i.raise("filebrowse"),i.isError&&!i.isUploadable&&i.clear(),r.focus()}),a(l,"reset",e.proxy(i.reset,i)),a(o.find(".fileinput-remove:not([disabled])"),"click",e.proxy(i.clear,i)),a(o.find(".fileinput-cancel"),"click",e.proxy(i.cancel,i)),i.isUploadable&&i.dropZoneEnabled&&i.showPreview&&i.initDragDrop(),i.isUploadable||a(l,"submit",e.proxy(i.submitForm,i)),a(i.$container.find(".fileinput-upload"),"click",function(t){var a,r=e(this),n=!r.hasClass("disabled")&&W(r.attr("disabled"));return i.isUploadable?(t.preventDefault(),void(n&&i.upload())):void(n&&"submit"!==r.attr("type")&&(a=r.closest("form"),a.length&&a.trigger("submit"),t.preventDefault()))})},submitForm:function(){var e=this,i=e.$element,t=i.get(0).files;return t&&e.minFileCount>0&&e.getFileCount(t.length)<e.minFileCount?(e.noFilesError({}),!1):!e.abort({})},abort:function(i){var t,a=this;return a.ajaxAborted&&"object"==typeof a.ajaxAborted&&void 0!==a.ajaxAborted.message?(t=e.extend(a.getOutData(),i),t.abortData=a.ajaxAborted.data||{},t.abortMessage=a.ajaxAborted.message,a.cancel(),a.setProgress(100),a.showUploadError(a.ajaxAborted.message,t,"filecustomerror"),!0):!1},noFilesError:function(e){var i=this,t=i.minFileCount>1?i.filePlural:i.fileSingle,a=i.msgFilesTooLess.replace("{n}",i.minFileCount).replace("{files}",t),r=i.$errorContainer;i.addError(a),i.isError=!0,i.updateFileDetails(0),r.fadeIn(800),i.raise("fileerror",[e]),i.clearFileInput(),d(i.$container,"has-error")},setProgress:function(e,i){var t=this,a=Math.min(e,100),r=100>a?t.progressTemplate:t.progressCompleteTemplate;i=i||t.$progress,W(r)||i.html(r.replace(/\{percent}/g,a))},lock:function(){var e=this;e.resetErrors(),e.disable(),e.showRemove&&d(e.$container.find(".fileinput-remove"),"hide"),e.showCancel&&e.$container.find(".fileinput-cancel").removeClass("hide"),e.raise("filelock",[e.filestack,e.getExtraData()])},unlock:function(e){var i=this;void 0===e&&(e=!0),i.enable(),i.showCancel&&d(i.$container.find(".fileinput-cancel"),"hide"),i.showRemove&&i.$container.find(".fileinput-remove").removeClass("hide"),e&&i.resetFileStack(),i.raise("fileunlock",[i.filestack,i.getExtraData()])},resetFileStack:function(){var i=this,t=0,a=[],r=[];i.getThumbs().each(function(){var n=e(this),l=n.attr("data-fileindex"),o=i.filestack[l];-1!==l&&(void 0!==o?(a[t]=o,r[t]=i.getFileName(o),n.attr({id:i.previewInitId+"-"+t,"data-fileindex":t}),t++):n.attr({id:"uploaded-"+K(),"data-fileindex":"-1"}))}),i.filestack=a,i.filenames=r},destroy:function(){var e=this,i=e.$container;i.find(".file-drop-zone").off(),e.$element.insertBefore(i).off(".fileinput").removeData(),i.off().remove()},refresh:function(i){var t=this,a=t.$element;i=i?e.extend(t.options,i):t.options,t.destroy(),a.fileinput(i),a.val()&&a.trigger("change.fileinput")},initDragDrop:function(){var i=this,t=i.$container.find(".file-drop-zone"),r="dragenter.fileinput dragover.fileinput drop.fileinput";a(t,"dragenter.fileinput dragover.fileinput",function(t){var a=e.inArray("Files",t.originalEvent.dataTransfer.types)>-1;return t.stopPropagation(),t.preventDefault(),i.isDisabled||!a?(t.originalEvent.dataTransfer.effectAllowed="none",void(t.originalEvent.dataTransfer.dropEffect="none")):void d(e(this),"file-highlighted")},!0),a(t,"dragleave",function(t){t.stopPropagation(),t.preventDefault(),i.isDisabled||e(this).removeClass("file-highlighted")}),a(t,"drop",function(t){t.preventDefault(),i.isDisabled||W(t.originalEvent.dataTransfer.files)||(i.change(t,"dragdrop"),e(this).removeClass("file-highlighted"))}),a(e(document),r,function(e){e.stopPropagation(),e.preventDefault()},!0)},setFileDropZoneTitle:function(){var e=this,i=e.$container.find(".file-drop-zone");i.find("."+e.dropZoneTitleClass).remove(),e.isUploadable&&e.showPreview&&0!==i.length&&!(e.getFileStack().length>0)&&e.dropZoneEnabled&&(0===i.find(".file-preview-frame").length&&W(e.defaultPreviewContent)&&i.prepend('<div class="'+e.dropZoneTitleClass+'">'+e.dropZoneTitle+"</div>"),e.$container.removeClass("file-input-new"),d(e.$container,"file-input-ajax-new"))},errorsExist:function(){var i,t=this;return t.$errorContainer.find("li").length?!0:(i=e(document.createElement("div")).html(t.$errorContainer.html()),i.find("span.kv-error-close").remove(),i.find("ul").remove(),e.trim(i.text()).length?!0:!1)},getMsgSelected:function(e){var i=this,t=1===e?i.fileSingle:i.filePlural;return i.msgSelected.replace("{n}",e).replace("{files}",t)},renderThumbProgress:function(){return'<div class="file-thumb-progress hide">'+this.progressTemplate.replace(/\{percent}/g,"0")+"</div>"},renderFileFooter:function(e,i){var t,a,r=this,n=r.fileActionSettings,l=r.getLayoutTemplate("footer");return r.isUploadable?(t=l.replace(/\{actions}/g,r.renderFileActions(!0,!0,!1,!1,!1)),a=t.replace(/\{caption}/g,e).replace(/\{width}/g,i).replace(/\{progress}/g,r.renderThumbProgress()).replace(/\{indicator}/g,n.indicatorNew).replace(/\{indicatorTitle}/g,n.indicatorNewTitle)):a=l.replace(/\{actions}/g,"").replace(/\{caption}/g,e).replace(/\{progress}/g,"").replace(/\{width}/g,i).replace(/\{indicator}/g,"").replace(/\{indicatorTitle}/g,""),a=J(a,r.previewThumbTags)},renderFileActions:function(e,i,t,a,r){if(!e&&!i)return"";var n=this,l=a===!1?"":' data-url="'+a+'"',o=r===!1?"":' data-key="'+r+'"',s=n.getLayoutTemplate("actionDelete"),d="",c=n.getLayoutTemplate("actions"),p=n.otherActionButtons.replace(/\{dataKey}/g,o),u=n.fileActionSettings,f=t?u.removeClass+" disabled":u.removeClass;return s=s.replace(/\{removeClass}/g,f).replace(/\{removeIcon}/g,u.removeIcon).replace(/\{removeTitle}/g,u.removeTitle).replace(/\{dataUrl}/g,l).replace(/\{dataKey}/g,o),e&&(d=n.getLayoutTemplate("actionUpload").replace(/\{uploadClass}/g,u.uploadClass).replace(/\{uploadIcon}/g,u.uploadIcon).replace(/\{uploadTitle}/g,u.uploadTitle)),c.replace(/\{delete}/g,s).replace(/\{upload}/g,d).replace(/\{other}/g,p)},setThumbStatus:function(e,i){var t=this;if(t.showPreview){var a="indicator"+i,r=a+"Title",n="file-preview-"+i.toLowerCase(),l=e.find(".file-upload-indicator"),o=t.fileActionSettings;e.removeClass("file-preview-success file-preview-error file-preview-loading"),"Error"===i&&e.find(".kv-file-upload").attr("disabled",!0),l.html(o[a]),l.attr("title",o[r]),e.addClass(n)}},clearPreview:function(){var e=this,i=e.$preview.find(e.showUploadedThumbs?".file-preview-frame:not(.file-preview-success)":".file-preview-frame");i.remove(),e.$preview.find(".file-preview-frame").length&&e.showPreview||e.resetUpload(),e.validateDefaultPreview()},initPreview:function(e){var i,t=this,a=t.initialCaption||"";return r.count(t.id)?(i=r.out(t.id),a=e&&t.initialCaption?t.initialCaption:i.caption,t.$preview.html(i.content),t.setCaption(a),void(W(i.content)||t.$container.removeClass("file-input-new"))):(t.clearPreview(),void(e?t.setCaption(a):t.initCaption()))},initPreviewDeletes:function(){var i=this,t=i.deleteExtraData||{},n=function(){var e=i.isUploadable?r.count(i.id):i.$element.get(0).files.length;0!==i.$preview.find(".kv-file-remove").length||e||(i.reset(),i.initialCaption="")};i.$preview.find(".kv-file-remove").each(function(){var l=e(this),o=l.data("url")||i.deleteUrl,s=l.data("key");if(!W(o)&&void 0!==s){var c,p,u,f,v=l.closest(".file-preview-frame"),g=r.data[i.id],m=v.data("fileindex");m=parseInt(m.replace("init_","")),u=W(g.config)&&W(g.config[m])?null:g.config[m],f=W(u)||W(u.extra)?t:u.extra,"function"==typeof f&&(f=f()),p={id:l.attr("id"),key:s,extra:f},c=e.extend({url:o,type:"POST",dataType:"json",data:e.extend({key:s},f),beforeSend:function(e){i.ajaxAborted=!1,i.raise("filepredelete",[s,e,f]),i.ajaxAborted?e.abort():(d(v,"file-uploading"),d(l,"disabled"))},success:function(e,t,a){var o,d;return W(e)||W(e.error)?(r.unset(i.id,m),o=r.count(i.id),d=o>0?i.getMsgSelected(o):"",i.raise("filedeleted",[s,a,f]),i.setCaption(d),v.removeClass("file-uploading").addClass("file-deleted"),void v.fadeOut("slow",function(){i.clearObjects(v),v.remove(),n(),o||0!==i.getFileStack().length||(i.setCaption(""),i.reset())})):(p.jqXHR=a,p.response=e,i.showError(e.error,p,"filedeleteerror"),v.removeClass("file-uploading"),l.removeClass("disabled"),void n())},error:function(e,t,a){var r=i.parseError(e,a);p.jqXHR=e,p.response={},i.showError(r,p,"filedeleteerror"),v.removeClass("file-uploading"),n()}},i.ajaxDeleteSettings),a(l,"click",function(){return i.validateMinCount()?void e.ajax(c):!1})}})},clearObjects:function(i){i.find("video audio").each(function(){this.pause(),e(this).remove()}),i.find("img object div").each(function(){e(this).remove()})},clearFileInput:function(){var i,t,a,r=this,n=r.$element;W(n.val())||(r.isIE9||r.isIE10?(i=n.closest("form"),t=e(document.createElement("form")),a=e(document.createElement("div")),n.before(a),i.length?i.after(t):a.after(t),t.append(n).trigger("reset"),a.before(n).remove(),t.remove()):n.val(""),r.fileInputCleared=!0)},resetUpload:function(){var e=this;e.uploadCache={content:[],config:[],tags:[],append:!0},e.uploadCount=0,e.uploadStatus={},e.uploadLog=[],e.uploadAsyncCount=0,e.loadedImages=[],e.totalImagesCount=0,e.$btnUpload.removeAttr("disabled"),e.setProgress(0),d(e.$progress,"hide"),e.resetErrors(!1),e.ajaxAborted=!1,e.ajaxRequests=[],e.resetCanvas()},resetCanvas:function(){var e=this;e.canvas&&e.imageCanvasContext&&e.imageCanvasContext.clearRect(0,0,e.canvas.width,e.canvas.height)},cancel:function(){var i,t=this,a=t.ajaxRequests,r=a.length;if(r>0)for(i=0;r>i;i+=1)t.cancelling=!0,a[i].abort();t.getThumbs().each(function(){var i=e(this),a=i.attr("data-fileindex");i.removeClass("file-uploading"),void 0!==t.filestack[a]&&(i.find(".kv-file-upload").removeClass("disabled").removeAttr("disabled"),i.find(".kv-file-remove").removeClass("disabled").removeAttr("disabled")),t.unlock()})},cleanMemory:function(e){var i=e.is("img")?e.attr("src"):e.find("source").attr("src");Q.revokeObjectURL(i)},hasInitialPreview:function(){var e=this;return!e.overwriteInitial&&r.count(e.id)},clear:function(){var i,t=this;t.$btnUpload.removeAttr("disabled"),t.getThumbs().find("video,audio,img").each(function(){t.cleanMemory(e(this))}),t.resetUpload(),t.clearStack(),t.clearFileInput(),t.resetErrors(!0),t.raise("fileclear"),t.hasInitialPreview()?(t.showFileIcon(),t.resetPreview(),t.initPreviewDeletes(),t.$container.removeClass("file-input-new")):(t.getThumbs().each(function(){t.clearObjects(e(this))}),t.isUploadable&&(r.data[t.id]={}),t.$preview.html(""),i=!t.overwriteInitial&&t.initialCaption.length>0?t.initialCaption:"",t.setCaption(i),t.$caption.attr("title",""),d(t.$container,"file-input-new"),t.validateDefaultPreview()),0===t.$container.find(".file-preview-frame").length&&(t.initCaption()||t.$captionContainer.find(".kv-caption-icon").hide()),t.hideFileIcon(),t.raise("filecleared"),t.$captionContainer.focus(),t.setFileDropZoneTitle()},resetPreview:function(){var e,i,t=this;r.count(t.id)?(e=r.out(t.id),t.$preview.html(e.content),i=t.initialCaption?t.initialCaption:e.caption,t.setCaption(i)):(t.clearPreview(),t.initCaption())},clearDefaultPreview:function(){var e=this;e.$preview.find(".file-default-preview").remove()},validateDefaultPreview:function(){var e=this;e.showPreview&&!W(e.defaultPreviewContent)&&(e.$preview.html('<div class="file-default-preview">'+e.defaultPreviewContent+"</div>"),e.$container.removeClass("file-input-new"))},resetPreviewThumbs:function(e){var i,t=this;return e?(t.clearPreview(),void t.clearStack()):void(t.hasInitialPreview()?(i=r.out(t.id),t.$preview.html(i.content),t.setCaption(i.caption),t.initPreviewDeletes()):t.clearPreview())},reset:function(){var e=this;e.resetPreview(),e.$container.find(".fileinput-filename").text(""),e.raise("filereset"),d(e.$container,"file-input-new"),(e.$preview.find(".file-preview-frame").length||e.isUploadable&&e.dropZoneEnabled)&&e.$container.removeClass("file-input-new"),e.setFileDropZoneTitle(),e.clearStack(),e.formdata={}},disable:function(){var e=this;e.isDisabled=!0,e.raise("filedisabled"),e.$element.attr("disabled","disabled"),e.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled"),e.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button").attr("disabled",!0),e.initDragDrop()},enable:function(){var e=this;e.isDisabled=!1,e.raise("fileenabled"),e.$element.removeAttr("disabled"),e.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled"),e.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button").removeAttr("disabled"),e.initDragDrop()},getThumbs:function(e){return e=e||"",this.$preview.find(".file-preview-frame:not(.file-preview-initial)"+e)},getExtraData:function(e,i){var t=this,a=t.uploadExtraData;return"function"==typeof t.uploadExtraData&&(a=t.uploadExtraData(e,i)),a},uploadExtra:function(i,t){var a=this,r=a.getExtraData(i,t);0!==r.length&&e.each(r,function(e,i){a.formdata.append(e,i)})},setAsyncUploadStatus:function(i,t,a){var r=this,n=0;r.setProgress(t,e("#"+i).find(".file-thumb-progress")),r.uploadStatus[i]=t,e.each(r.uploadStatus,function(e,i){n+=i}),r.setProgress(Math.ceil(n/a))},initXhr:function(e,i,t){var a=this;return e.upload&&e.upload.addEventListener("progress",function(e){var r=0,n=e.loaded||e.position,l=e.total;e.lengthComputable&&(r=Math.ceil(n/l*100)),i?a.setAsyncUploadStatus(i,r,t):a.setProgress(Math.ceil(r))},!1),e},ajaxSubmit:function(i,t,a,r,n,l){var o,s=this;s.raise("filepreajax",[n,l]),s.uploadExtra(n,l),o=e.extend({xhr:function(){var i=e.ajaxSettings.xhr();return s.initXhr(i,n,s.getFileStack().length)},url:s.uploadUrl,type:"POST",dataType:"json",data:s.formdata,cache:!1,processData:!1,contentType:!1,beforeSend:i,success:t,complete:a,error:r},s.ajaxSettings),s.ajaxRequests.push(e.ajax(o))},initUploadSuccess:function(i,t,a){var n,l,o,s,d,c,p,u,f=this;f.showPreview&&"object"==typeof i&&!e.isEmptyObject(i)&&void 0!==i.initialPreview&&i.initialPreview.length>0&&(f.hasInitData=!0,d=i.initialPreview||[],c=i.initialPreviewConfig||[],p=i.initialPreviewThumbTags||[],n=void 0===i.append||i.append?!0:!1,f.overwriteInitial=!1,void 0!==t?a?(u=t.attr("data-fileindex"),f.uploadCache.content[u]=d[0],f.uploadCache.config[u]=c[0],f.uploadCache.tags[u]=p[0],f.uploadCache.append=n):(o=r.add(f.id,d,c[0],p[0],n),l=r.get(f.id,o,!1),s=e(l).hide(),t.after(s).fadeOut("slow",function(){s.fadeIn("slow").css("display:inline-block"),f.initPreviewDeletes(),f.clearFileInput(),t.remove()})):(r.set(f.id,d,c,p,n),f.initPreview(),f.initPreviewDeletes()))},initSuccessThumbs:function(){var i=this;i.showPreview&&i.getThumbs(".file-preview-success").each(function(){var t=e(this),r=t.find(".kv-file-remove");r.removeAttr("disabled"),a(r,"click",function(){var e=i.raise("filesuccessremove",[t.attr("id"),t.data("fileindex")]);i.cleanMemory(t),e!==!1&&t.fadeOut("slow",function(){t.remove(),i.$preview.find(".file-preview-frame").length||i.reset()})})})},checkAsyncComplete:function(){var i,t,a=this;for(t=0;t<a.filestack.length;t++)if(a.filestack[t]&&(i=a.previewInitId+"-"+t,-1===e.inArray(i,a.uploadLog)))return!1;return a.uploadAsyncCount===a.uploadLog.length},uploadSingle:function(i,t,a){var n,l,o,s,c,p,u,f,v,g,m=this,h=m.getFileStack().length,w=new FormData,b=m.previewInitId+"-"+i,C=m.filestack.length>0||!e.isEmptyObject(m.uploadExtraData),x={id:b,index:i};m.formdata=w,m.showPreview&&(l=e("#"+b+":not(.file-preview-initial)"),s=l.find(".kv-file-upload"),c=l.find(".kv-file-remove"),e("#"+b).find(".file-thumb-progress").removeClass("hide")),0===h||!C||s&&s.hasClass("disabled")||m.abort(x)||(g=function(e,i){
  18 +m.updateStack(e,void 0),m.uploadLog.push(i),m.checkAsyncComplete()&&(m.fileBatchCompleted=!0)},o=function(){m.fileBatchCompleted&&setTimeout(function(){m.showPreview&&(r.set(m.id,m.uploadCache.content,m.uploadCache.config,m.uploadCache.tags,m.uploadCache.append),m.hasInitData&&(m.initPreview(),m.initPreviewDeletes())),m.unlock(),m.clearFileInput(),m.raise("filebatchuploadcomplete",[m.filestack,m.getExtraData()]),m.uploadCount=0,m.uploadStatus={},m.uploadLog=[],m.setProgress(100)},100)},p=function(t){n=m.getOutData(t),m.fileBatchCompleted=!1,m.showPreview&&(l.hasClass("file-preview-success")||(m.setThumbStatus(l,"Loading"),d(l,"file-uploading")),s.attr("disabled",!0),c.attr("disabled",!0)),a||m.lock(),m.raise("filepreupload",[n,b,i]),x=e.extend(x,n),m.abort(x)&&(t.abort(),m.setProgress(100))},u=function(t,r,o){n=m.getOutData(o,t),x=e.extend(x,n),setTimeout(function(){W(t)||W(t.error)?(m.showPreview&&(m.setThumbStatus(l,"Success"),s.hide(),m.initUploadSuccess(t,l,a)),m.raise("fileuploaded",[n,b,i]),a?g(i,b):m.updateStack(i,void 0)):(m.setThumbStatus(l,"Error"),m.showUploadError(t.error,x),a&&g(i,b))},100)},f=function(){setTimeout(function(){m.showPreview&&(s.removeAttr("disabled"),c.removeAttr("disabled"),l.removeClass("file-uploading")),a?o():(m.unlock(!1),m.clearFileInput()),m.initSuccessThumbs()},100)},v=function(r,n,o){var s=m.parseError(r,o,a?t[i].name:null);setTimeout(function(){a&&g(i,b),m.uploadStatus[b]=100,m.setThumbStatus(l,"Error"),x=e.extend(x,m.getOutData(r)),m.showUploadError(s,x)},100)},w.append(m.uploadFileAttr,t[i],m.filenames[i]),w.append("file_id",i),m.ajaxSubmit(p,u,f,v,b,i))},uploadBatch:function(){var i,t,a,r,n,l=this,o=l.filestack,s=o.length,c={},p=l.filestack.length>0||!e.isEmptyObject(l.uploadExtraData);l.formdata=new FormData,0!==s&&p&&!l.abort(c)&&(i=function(){e.each(o,function(e){l.updateStack(e,void 0)}),l.clearFileInput()},t=function(i){l.lock();var t=l.getOutData(i);l.showPreview&&l.getThumbs().each(function(){var i=e(this),t=i.find(".kv-file-upload"),a=i.find(".kv-file-remove");i.hasClass("file-preview-success")||(l.setThumbStatus(i,"Loading"),d(i,"file-uploading")),t.attr("disabled",!0),a.attr("disabled",!0)}),l.raise("filebatchpreupload",[t]),l.abort(t)&&(i.abort(),l.setProgress(100))},a=function(t,a,r){var n=l.getOutData(r,t),o=l.getThumbs(),s=0,d=W(t)||W(t.errorkeys)?[]:t.errorkeys;W(t)||W(t.error)?(l.raise("filebatchuploadsuccess",[n]),i(),l.showPreview?(o.each(function(){var i=e(this),t=i.find(".kv-file-upload");i.find(".kv-file-upload").hide(),l.setThumbStatus(i,"Success"),i.removeClass("file-uploading"),t.removeAttr("disabled")}),l.initUploadSuccess(t)):l.reset()):(l.showPreview&&(o.each(function(){var i=e(this),t=i.find(".kv-file-remove"),a=i.find(".kv-file-upload");return i.removeClass("file-uploading"),a.removeAttr("disabled"),t.removeAttr("disabled"),0===d.length?void l.setThumbStatus(i,"Error"):(-1!==e.inArray(s,d)?l.setThumbStatus(i,"Error"):(i.find(".kv-file-upload").hide(),l.setThumbStatus(i,"Success"),l.updateStack(s,void 0)),void s++)}),l.initUploadSuccess(t)),l.showUploadError(t.error,n,"filebatchuploaderror"))},r=function(){l.setProgress(100),l.unlock(),l.initSuccessThumbs(),l.clearFileInput(),l.raise("filebatchuploadcomplete",[l.filestack,l.getExtraData()])},n=function(i,t,a){var r=l.getOutData(i),n=l.parseError(i,a);l.showUploadError(n,r,"filebatchuploaderror"),l.uploadFileCount=s-1,l.showPreview&&(l.getThumbs().each(function(){var i=e(this),t=i.attr("data-fileindex");i.removeClass("file-uploading"),void 0!==l.filestack[t]&&l.setThumbStatus(i,"Error")}),l.getThumbs().removeClass("file-uploading"),l.getThumbs(" .kv-file-upload").removeAttr("disabled"),l.getThumbs(" .kv-file-delete").removeAttr("disabled"))},e.each(o,function(e,i){W(o[e])||l.formdata.append(l.uploadFileAttr,i,l.filenames[e])}),l.ajaxSubmit(t,a,r,n))},uploadExtraOnly:function(){var e,i,t,a,r=this,n={};r.formdata=new FormData,r.abort(n)||(e=function(e){r.lock();var i=r.getOutData(e);r.raise("filebatchpreupload",[i]),r.setProgress(50),n.data=i,n.xhr=e,r.abort(n)&&(e.abort(),r.setProgress(100))},i=function(e,i,t){var a=r.getOutData(t,e);W(e)||W(e.error)?(r.raise("filebatchuploadsuccess",[a]),r.clearFileInput(),r.initUploadSuccess(e)):r.showUploadError(e.error,a,"filebatchuploaderror")},t=function(){r.setProgress(100),r.unlock(),r.clearFileInput(),r.raise("filebatchuploadcomplete",[r.filestack,r.getExtraData()])},a=function(e,i,t){var a=r.getOutData(e),l=r.parseError(e,t);n.data=a,r.showUploadError(l,a,"filebatchuploaderror")},r.ajaxSubmit(e,i,t,a))},upload:function(){var i,t,a,r=this,n=r.getFileStack().length,l={},o=!e.isEmptyObject(r.getExtraData());if(r.minFileCount>0&&r.getFileCount(n)<r.minFileCount)return void r.noFilesError(l);if(r.isUploadable&&!r.isDisabled&&(0!==n||o)){if(r.resetUpload(),r.$progress.removeClass("hide"),r.uploadCount=0,r.uploadStatus={},r.uploadLog=[],r.lock(),r.setProgress(2),0===n&&o)return void r.uploadExtraOnly();if(a=r.filestack.length,r.hasInitData=!1,r.uploadAsync){for(t=r.getOutData(),r.raise("filebatchpreupload",[t]),r.fileBatchCompleted=!1,r.uploadCache={content:[],config:[],tags:[],append:!0},r.uploadAsyncCount=r.getFileStack().length,i=0;a>i;i++)r.uploadCache.content[i]=null,r.uploadCache.config[i]=null,r.uploadCache.tags[i]=null;for(i=0;a>i;i++)void 0!==r.filestack[i]&&r.uploadSingle(i,r.filestack,!0)}else r.uploadBatch()}},initFileActions:function(){var i=this;i.showPreview&&(i.$preview.find(".kv-file-remove").each(function(){var t,n,l,o,s=e(this),d=s.closest(".file-preview-frame"),c=d.attr("id"),p=d.attr("data-fileindex");a(s,"click",function(){return o=i.raise("filepreremove",[c,p]),o!==!1&&i.validateMinCount()?(t=d.hasClass("file-preview-error"),i.cleanMemory(d),void d.fadeOut("slow",function(){i.updateStack(p,void 0),i.clearObjects(d),d.remove(),c&&t&&i.$errorContainer.find('li[data-file-id="'+c+'"]').fadeOut("fast",function(){e(this).remove(),i.errorsExist()||i.resetErrors()});var a=i.getFileStack(!0),o=a.length,s=r.count(i.id),u=i.showPreview&&i.$preview.find(".file-preview-frame").length;i.clearFileInput(),0!==o||0!==s||u?(n=s+o,l=n>1?i.getMsgSelected(n):a[0]?i.getFileNames()[0]:"",i.setCaption(l)):i.reset(),i.raise("fileremoved",[c,p])})):!1})}),i.$preview.find(".kv-file-upload").each(function(){var t=e(this);a(t,"click",function(){var e=t.closest(".file-preview-frame"),a=e.attr("data-fileindex");e.hasClass("file-preview-error")||i.uploadSingle(a,i.filestack,!1)})}))},hideFileIcon:function(){this.overwriteInitial&&this.$captionContainer.find(".kv-caption-icon").hide()},showFileIcon:function(){this.$captionContainer.find(".kv-caption-icon").show()},addError:function(e){var i=this,t=i.$errorContainer;e&&t.length&&(t.html(i.errorCloseButton+e),t.find(".kv-error-close").off("click").on("click",function(){t.fadeOut("slow")}))},resetErrors:function(e){var i=this,t=i.$errorContainer;i.isError=!1,i.$container.removeClass("has-error"),t.html(""),e?t.fadeOut("slow"):t.hide()},showFolderError:function(e){var i=this,t=i.$errorContainer;e&&(i.addError(i.msgFoldersNotAllowed.replace(/\{n}/g,e)),t.fadeIn(800),d(i.$container,"has-error"),i.raise("filefoldererror",[e]))},showUploadError:function(e,i,t){var a=this,r=a.$errorContainer,n=t||"fileuploaderror",l=i&&i.id?'<li data-file-id="'+i.id+'">'+e+"</li>":"<li>"+e+"</li>";return 0===r.find("ul").length?a.addError("<ul>"+l+"</ul>"):r.find("ul").append(l),r.fadeIn(800),a.raise(n,[i]),a.$container.removeClass("file-input-new"),d(a.$container,"has-error"),!0},showError:function(e,i,t){var a=this,r=a.$errorContainer,n=t||"fileerror";return i=i||{},i.reader=a.reader,a.addError(e),r.fadeIn(800),a.raise(n,[i]),a.isUploadable||a.clearFileInput(),a.$container.removeClass("file-input-new"),d(a.$container,"has-error"),a.$btnUpload.attr("disabled",!0),!0},errorHandler:function(e,i){var t=this,a=e.target.error;t.showError(a.code===a.NOT_FOUND_ERR?t.msgFileNotFound.replace("{name}",i):a.code===a.SECURITY_ERR?t.msgFileSecured.replace("{name}",i):a.code===a.NOT_READABLE_ERR?t.msgFileNotReadable.replace("{name}",i):a.code===a.ABORT_ERR?t.msgFilePreviewAborted.replace("{name}",i):t.msgFilePreviewError.replace("{name}",i))},parseFileType:function(e){var i,t,a,r,n=this;for(r=0;r<N.length;r+=1)if(a=N[r],i=_(a,n.fileTypeSettings)?n.fileTypeSettings[a]:H[a],t=i(e.type,e.name)?a:"",!W(t))return t;return"other"},previewDefault:function(i,t,a){if(this.showPreview){var r=this,n="",l=i?i.name:"",o=Q.createObjectURL(i),s=t.slice(t.lastIndexOf("-")+1),d=r.previewSettings.other||Z.other,c=r.renderFileFooter(i.name,d.width),p=r.parseFilePreviewIcon(r.getPreviewTemplate("other"),l);a===!0&&(r.isUploadable||(c+='<div class="file-other-error" title="'+r.fileActionSettings.indicatorErrorTitle+'">'+r.fileActionSettings.indicatorError+"</div>")),r.clearDefaultPreview(),r.$preview.append("\n"+p.replace(/\{previewId}/g,t).replace(/\{frameClass}/g,n).replace(/\{fileindex}/g,s).replace(/\{caption}/g,r.slug(i.name)).replace(/\{width}/g,d.width).replace(/\{height}/g,d.height).replace(/\{type}/g,i.type).replace(/\{data}/g,o).replace(/\{footer}/g,c)),a===!0&&r.isUploadable&&r.setThumbStatus(e("#"+t),"Error")}},previewFile:function(e,i,t,a,r){if(this.showPreview){var n,l,o,s=this,d=s.parseFileType(i),c=i?i.name:"",p=s.slug(c),u=s.allowedPreviewTypes,f=s.allowedPreviewMimeTypes,v=s.getPreviewTemplate(d),g=u&&u.indexOf(d)>=0,m=_(d,s.previewSettings)?s.previewSettings[d]:Z[d],h=f&&-1!==f.indexOf(i.type),w=s.renderFileFooter(p,m.width),b="",C=a.slice(a.lastIndexOf("-")+1);g||h?(v=s.parseFilePreviewIcon(v,c.split(".").pop()),"text"===d?(l=X(t.target.result),o="text-"+K(),n=v.replace(/\{zoom}/g,s.getLayoutTemplate("zoom")),b=s.getLayoutTemplate("modal").replace("{id}",o).replace(/\{title}/g,p).replace(/\{body}/g,l).replace(/\{heading}/g,s.msgZoomModalHeading),n=n.replace(/\{previewId}/g,a).replace(/\{caption}/g,p).replace(/\{width}/g,m.width).replace(/\{height}/g,m.height).replace(/\{frameClass}/g,"").replace(/\{zoomInd}/g,s.zoomIndicator).replace(/\{footer}/g,w).replace(/\{fileindex}/g,C).replace(/\{type}/g,i.type).replace(/\{zoomTitle}/g,s.msgZoomTitle).replace(/\{dialog}/g,"$('#"+o+"').modal('show')").replace(/\{data}/g,l)+b):n=v.replace(/\{previewId}/g,a).replace(/\{caption}/g,p).replace(/\{frameClass}/g,"").replace(/\{type}/g,i.type).replace(/\{fileindex}/g,C).replace(/\{width}/g,m.width).replace(/\{height}/g,m.height).replace(/\{footer}/g,w).replace(/\{data}/g,r),s.clearDefaultPreview(),s.$preview.append("\n"+n),s.validateImage(e,a,p,i.type)):s.previewDefault(i,a)}},slugDefault:function(e){return W(e)?"":e.split(/(\\|\/)/g).pop().replace(/[^\w\u00C0-\u017F\-.\\\/ ]+/g,"")},readFiles:function(i){this.reader=new FileReader;var t,a=this,r=a.$element,n=a.$preview,l=a.reader,o=a.$previewContainer,s=a.$previewStatus,d=a.msgLoading,c=a.msgProgress,p=a.previewInitId,u=i.length,f=a.fileTypeSettings,v=a.filestack.length,g=function(r,n,l,o){var s=e.extend(a.getOutData({},{},i),{id:l,index:o}),d={id:l,index:o,file:n,files:i};return a.previewDefault(n,l,!0),a.isUploadable&&a.pushStack(void 0),setTimeout(t(o+1),100),a.initFileActions(),a.isUploadable?a.showUploadError(r,s):a.showError(r,d)};a.loadedImages=[],a.totalImagesCount=0,e.each(i,function(e,i){var t="image",r=_(t,a.fileTypeSettings)?a.fileTypeSettings[t]:H[t];r&&r(i.type)&&a.totalImagesCount++}),t=function(e){if(W(r.attr("multiple"))&&(u=1),e>=u)return a.isUploadable&&a.filestack.length>0?a.raise("filebatchselected",[a.getFileStack()]):a.raise("filebatchselected",[i]),o.removeClass("file-thumb-loading"),void s.html("");var m,h,w,b,C,x,y=v+e,T=p+"-"+y,F=i[e],I=a.slug(F.name),E=(F.size||0)/1e3,k="",S=Q.createObjectURL(F),$=0,P=a.allowedFileTypes,D=W(P)?"":P.join(", "),U=a.allowedFileExtensions,A=W(U)?"":U.join(", ");if(W(U)||(k=new RegExp("\\.("+U.join("|")+")$","i")),E=E.toFixed(2),a.maxFileSize>0&&E>a.maxFileSize)return b=a.msgSizeTooLarge.replace("{name}",I).replace("{size}",E).replace("{maxSize}",a.maxFileSize),void(a.isError=g(b,F,T,e));if(!W(P)&&q(P)){for(w=0;w<P.length;w+=1)C=P[w],h=f[C],x=void 0!==h&&h(F.type,I),$+=W(x)?0:x.length;if(0===$)return b=a.msgInvalidFileType.replace("{name}",I).replace("{types}",D),void(a.isError=g(b,F,T,e))}return 0!==$||W(U)||!q(U)||W(k)||(x=I.match(k),$+=W(x)?0:x.length,0!==$)?a.showPreview?(n.length>0&&void 0!==FileReader?(s.html(d.replace("{index}",e+1).replace("{files}",u)),o.addClass("file-thumb-loading"),l.onerror=function(e){a.errorHandler(e,I)},l.onload=function(i){a.previewFile(e,F,i,T,S),a.initFileActions()},l.onloadend=function(){b=c.replace("{index}",e+1).replace("{files}",u).replace("{percent}",50).replace("{name}",I),setTimeout(function(){s.html(b),a.updateFileDetails(u),t(e+1)},100),a.raise("fileloaded",[F,T,e,l])},l.onprogress=function(i){if(i.lengthComputable){var t=i.loaded/i.total*100,a=Math.ceil(t);b=c.replace("{index}",e+1).replace("{files}",u).replace("{percent}",a).replace("{name}",I),setTimeout(function(){s.html(b)},100)}},m=_("text",f)?f.text:H.text,m(F.type,I)?l.readAsText(F,a.textEncoding):l.readAsArrayBuffer(F)):(a.previewDefault(F,T),setTimeout(function(){t(e+1),a.updateFileDetails(u)},100),a.raise("fileloaded",[F,T,e,l])),void a.pushStack(F)):(a.pushStack(F),setTimeout(t(e+1),100),void a.raise("fileloaded",[F,T,e,l])):(b=a.msgInvalidFileExtension.replace("{name}",I).replace("{extensions}",A),void(a.isError=g(b,F,T,e)))},t(0),a.updateFileDetails(u,!1)},updateFileDetails:function(e){var i=this,t=i.$element,a=i.getFileStack(),n=t.val()||a.length&&a[0].name||"",l=i.slug(n),o=i.isUploadable?a.length:e,s=r.count(i.id)+o,d=o>1?i.getMsgSelected(s):l;i.isError?(i.$previewContainer.removeClass("file-thumb-loading"),i.$previewStatus.html(""),i.$captionContainer.find(".kv-caption-icon").hide()):i.showFileIcon(),i.setCaption(d,i.isError),i.$container.removeClass("file-input-new file-input-ajax-new"),1===arguments.length&&i.raise("fileselect",[e,l]),r.count(i.id)&&i.initPreviewDeletes()},validateMinCount:function(){var e=this,i=e.isUploadable?e.getFileStack().length:e.$element.get(0).files.length;return e.validateInitialCount&&e.minFileCount>0&&e.getFileCount(i-1)<e.minFileCount?(e.noFilesError({}),!1):!0},getFileCount:function(e){var i=this,t=0;return i.validateInitialCount&&!i.overwriteInitial&&(t=r.count(i.id),e+=t),e},change:function(i){var t=this,a=t.$element;if(!t.isUploadable&&W(a.val())&&t.fileInputCleared)return void(t.fileInputCleared=!1);t.fileInputCleared=!1;var n,l,o,s,d,c,p=arguments.length>1,u=p?i.originalEvent.dataTransfer.files:a.get(0).files,f=W(a.attr("multiple")),v=0,g=0,m=t.filestack.length,h=t.isUploadable,w=f&&m>0,b=function(i,a,r,n){var l=e.extend(t.getOutData({},{},u),{id:r,index:n}),o={id:r,index:n,file:a,files:u};return t.isUploadable?t.showUploadError(i,l):t.showError(i,o)};if(t.reader=null,t.resetUpload(),t.hideFileIcon(),t.isUploadable&&t.$container.find(".file-drop-zone ."+t.dropZoneTitleClass).remove(),p)for(n=[];u[v];)s=u[v],s.type||s.size%4096!==0?n.push(s):g++,v++;else n=void 0===i.target.files?i.target&&i.target.value?[{name:i.target.value.replace(/^.+\\/,"")}]:[]:i.target.files;if(W(n)||0===n.length)return h||t.clear(),t.showFolderError(g),void t.raise("fileselectnone");if(t.resetErrors(),c=n.length,o=t.isUploadable?t.getFileStack().length+c:c,o=t.getFileCount(o),t.maxFileCount>0&&o>t.maxFileCount){if(!t.autoReplace||c>t.maxFileCount)return d=t.autoReplace&&c>t.maxFileCount?c:o,l=t.msgFilesTooMany.replace("{m}",t.maxFileCount).replace("{n}",d),t.isError=b(l,null,null,null),t.$captionContainer.find(".kv-caption-icon").hide(),t.setCaption("",!0),void t.$container.removeClass("file-input-new file-input-ajax-new");o>t.maxFileCount&&t.resetPreviewThumbs(h)}else!h||w?(t.resetPreviewThumbs(!1),w&&t.clearStack()):!h||0!==m||r.count(t.id)&&!t.overwriteInitial||t.resetPreviewThumbs(!0);t.isPreviewable?t.readFiles(n):t.updateFileDetails(1),t.showFolderError(g)},getFileName:function(e){return e&&e.name?this.slug(e.name):void 0},getFileNames:function(e){var i=this;return i.filenames.filter(function(i){return e?void 0!==i:void 0!==i&&null!==i})},getFileStack:function(e){var i=this;return i.filestack.filter(function(i){return e?void 0!==i:void 0!==i&&null!==i})},clearStack:function(){var e=this;e.filestack=[],e.filenames=[]},updateStack:function(e,i){var t=this;t.filestack[e]=i,t.filenames[e]=t.getFileName(i)},pushStack:function(e){var i=this;i.filestack.push(e),i.filenames.push(i.getFileName(e))},checkDimensions:function(e,i,t,a,r,n,l){var o,s,d,c,p=this,u="Small"===i?"min":"max",f=p[u+"Image"+n];!W(f)&&t.length&&(d=t[0],s="Width"===n?d.naturalWidth||d.width:d.naturalHeight||d.height,c="Small"===i?s>=f:f>=s,c||(o=p["msgImage"+n+i].replace("{name}",r).replace("{size}",f),p.showUploadError(o,l),p.setThumbStatus(a,"Error"),p.updateStack(e,null)))},validateImage:function(e,i,t,r){var n,l,o,s=this,d=s.$preview,c=d.find("#"+i),p=c.find("img");t=t||"Untitled",p.length&&a(p,"load",function(){l=c.width(),o=d.width(),l>o&&(p.css("width","100%"),c.css("width","97%")),n={ind:e,id:i},s.checkDimensions(e,"Small",p,c,t,"Width",n),s.checkDimensions(e,"Small",p,c,t,"Height",n),s.resizeImage||(s.checkDimensions(e,"Large",p,c,t,"Width",n),s.checkDimensions(e,"Large",p,c,t,"Height",n)),s.raise("fileimageloaded",[i]),s.loadedImages.push({ind:e,img:p,thumb:c,pid:i,typ:r}),s.validateAllImages(),Q.revokeObjectURL(p.attr("src"))})},validateAllImages:function(){var e,i,t,a,r,n,l,o=this,s={};if(o.loadedImages.length===o.totalImagesCount&&(o.raise("fileimagesloaded"),o.resizeImage)){for(l=o.isUploadable?o.showUploadError:o.showError,e=0;e<o.loadedImages.length;e++)i=o.loadedImages[e],t=i.img,a=i.thumb,r=i.pid,n=i.ind,s={id:r,index:n},o.getResizedImage(t[0],i.typ,r,n)||(l(o.msgImageResizeError,s,"fileimageresizeerror"),o.setThumbStatus(a,"Error"),o.updateStack(n,void 0));o.raise("fileimagesresized")}},getResizedImage:function(e,i,t,a){var r,n,l=this,o=e.naturalWidth,s=e.naturalHeight,d=1,c=l.maxImageWidth||o,p=l.maxImageHeight||s,u=o&&s,f=l.imageCanvas,v=l.imageCanvasContext;if(!u)return!1;if(o===c&&s===p)return!0;i=i||l.resizeDefaultImageType,r=o>c,n=s>p,d="width"===l.resizePreference?r?c/o:n?p/s:1:n?p/s:r?c/o:1,l.resetCanvas(),o*=d,s*=d,f.width=o,f.height=s;try{return v.drawImage(e,0,0,o,s),f.toBlob(function(e){l.raise("fileimageresized",[t,a]),l.filestack[a]=e},i,l.resizeQuality),!0}catch(g){return!1}},initCaption:function(){var e=this,i=e.initialCaption||"";return e.overwriteInitial||W(i)?(e.$caption.html(""),!1):(e.setCaption(i),!0)},setCaption:function(i,t){var a,r,n=this;if(t)a=e("<div>"+n.msgValidationError+"</div>").text(),r='<span class="'+n.msgValidationErrorClass+'">'+n.msgValidationErrorIcon+a+"</span>";else{if(W(i)||0===n.$caption.length)return;a=e("<div>"+i+"</div>").text(),r=n.getLayoutTemplate("icon")+a}n.$caption.html(r),n.$caption.attr("title",a),n.$captionContainer.find(".file-caption-ellipsis").attr("title",a)},initBrowse:function(e){var i=this;i.$btnFile=e.find(".btn-file"),i.$btnFile.append(i.$element)},createContainer:function(){var i=this,t=e(document.createElement("div")).attr({"class":"file-input file-input-new"}).html(i.renderMain());return i.$element.before(t),i.initBrowse(t),t},refreshContainer:function(){var e=this,i=e.$container;i.before(e.$element),i.html(e.renderMain()),e.initBrowse(i)},renderMain:function(){var e=this,i=e.isUploadable&&e.dropZoneEnabled?" file-drop-zone":"file-drop-disabled",t=e.showClose?e.getLayoutTemplate("close"):"",a=e.showPreview?e.getLayoutTemplate("preview").replace(/\{class}/g,e.previewClass).replace(/\{dropClass}/g,i):"",r=e.isDisabled?e.captionClass+" file-caption-disabled":e.captionClass,n=e.captionTemplate.replace(/\{class}/g,r+" kv-fileinput-caption");return e.mainTemplate.replace(/\{class}/g,e.mainClass).replace(/\{preview}/g,a).replace(/\{close}/g,t).replace(/\{caption}/g,n).replace(/\{upload}/g,e.renderButton("upload")).replace(/\{remove}/g,e.renderButton("remove")).replace(/\{cancel}/g,e.renderButton("cancel")).replace(/\{browse}/g,e.renderButton("browse"))},renderButton:function(e){var i=this,t=i.getLayoutTemplate("btnDefault"),a=i[e+"Class"],r=i[e+"Title"],n=i[e+"Icon"],l=i[e+"Label"],o=i.isDisabled?" disabled":"",s="button";switch(e){case"remove":if(!i.showRemove)return"";break;case"cancel":if(!i.showCancel)return"";a+=" hide";break;case"upload":if(!i.showUpload)return"";i.isUploadable&&!i.isDisabled?t=i.getLayoutTemplate("btnLink").replace("{href}",i.uploadUrl):s="submit";break;case"browse":t=i.getLayoutTemplate("btnBrowse");break;default:return""}return a+="browse"===e?" btn-file":" fileinput-"+e+" fileinput-"+e+"-button",W(l)||(l=' <span class="'+i.buttonLabelClass+'">'+l+"</span>"),t.replace("{type}",s).replace("{css}",a).replace("{title}",r).replace("{status}",o).replace("{icon}",n).replace("{label}",l)}},e.fn.fileinput=function(t){if(l()||i(9)){var a=Array.apply(null,arguments),r=[];switch(a.shift(),this.each(function(){var i=e(this),n=i.data("fileinput"),l="object"==typeof t&&t,o=l.language||i.data("language")||"en",s=e.fn.fileinput.defaults;n||("en"===o||W(e.fn.fileinputLocales[o])||e.extend(s,e.fn.fileinputLocales[o]),n=new Y(this,e.extend(s,l,i.data())),i.data("fileinput",n)),"string"==typeof t&&r.push(n[t].apply(n,a))}),r.length){case 0:return this;case 1:return r[0];default:return r}}},e.fn.fileinput.defaults={language:"en",showCaption:!0,showPreview:!0,showRemove:!0,showUpload:!0,showCancel:!0,showClose:!0,showUploadedThumbs:!0,autoReplace:!1,mainClass:"",previewClass:"",captionClass:"",mainTemplate:null,initialCaption:"",initialPreview:[],initialPreviewDelimiter:"*$$*",initialPreviewConfig:[],initialPreviewThumbTags:[],previewThumbTags:{},initialPreviewShowDelete:!0,deleteUrl:"",deleteExtraData:{},overwriteInitial:!0,layoutTemplates:M,previewTemplates:B,allowedPreviewTypes:N,allowedPreviewMimeTypes:null,allowedFileTypes:null,allowedFileExtensions:null,defaultPreviewContent:null,customLayoutTags:{},customPreviewTags:{},previewSettings:Z,fileTypeSettings:H,previewFileIcon:'<i class="glyphicon glyphicon-file"></i>',previewFileIconClass:"file-icon-4x",previewFileIconSettings:{},previewFileExtSettings:{},buttonLabelClass:"hidden-xs",browseIcon:'<i class="glyphicon glyphicon-folder-open"></i>',browseClass:"btn btn-primary",removeIcon:'<i class="glyphicon glyphicon-trash"></i>',removeClass:"btn btn-default",cancelIcon:'<i class="glyphicon glyphicon-ban-circle"></i>',cancelClass:"btn btn-default",uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',uploadClass:"btn btn-default",uploadUrl:null,uploadAsync:!0,uploadExtraData:{},minImageWidth:null,minImageHeight:null,maxImageWidth:null,maxImageHeight:null,resizeImage:!1,resizePreference:"width",resizeQuality:.92,resizeDefaultImageType:"image/jpeg",maxFileSize:0,minFileCount:0,maxFileCount:0,validateInitialCount:!1,msgValidationErrorClass:"text-danger",msgValidationErrorIcon:'<i class="glyphicon glyphicon-exclamation-sign"></i> ',msgErrorClass:"file-error-message",progressThumbClass:"progress-bar progress-bar-success progress-bar-striped active",progressClass:"progress-bar progress-bar-success progress-bar-striped active",progressCompleteClass:"progress-bar progress-bar-success",previewFileType:"image",zoomIndicator:'<i class="glyphicon glyphicon-zoom-in"></i>',elCaptionContainer:null,elCaptionText:null,elPreviewContainer:null,elPreviewImage:null,elPreviewStatus:null,elErrorContainer:null,errorCloseButton:'<span class="close kv-error-close">&times;</span>',slugCallback:null,dropZoneEnabled:!0,dropZoneTitleClass:"file-drop-zone-title",fileActionSettings:{},otherActionButtons:"",textEncoding:"UTF-8",ajaxSettings:{},ajaxDeleteSettings:{},showAjaxErrorDetails:!0},e.fn.fileinputLocales.en={fileSingle:"file",filePlural:"files",browseLabel:"Browse &hellip;",removeLabel:"Remove",removeTitle:"Clear selected files",cancelLabel:"Cancel",cancelTitle:"Abort ongoing upload",uploadLabel:"Upload",uploadTitle:"Upload selected files",msgZoomTitle:"View details",msgZoomModalHeading:"Detailed Preview",msgSizeTooLarge:'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',msgFilesTooLess:"You must select at least <b>{n}</b> {files} to upload.",msgFilesTooMany:"Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.",msgFileNotFound:'File "{name}" not found!',msgFileSecured:'Security restrictions prevent reading the file "{name}".',msgFileNotReadable:'File "{name}" is not readable.',msgFilePreviewAborted:'File preview aborted for "{name}".',msgFilePreviewError:'An error occurred while reading the file "{name}".',msgInvalidFileType:'Invalid type for file "{name}". Only "{types}" files are supported.',msgInvalidFileExtension:'Invalid extension for file "{name}". Only "{extensions}" files are supported.',msgUploadAborted:"The file upload was aborted",msgValidationError:"File Upload Error",msgLoading:"Loading file {index} of {files} &hellip;",msgProgress:"Loading file {index} of {files} - {name} - {percent}% completed.",msgSelected:"{n} {files} selected",msgFoldersNotAllowed:"Drag & drop files only! {n} folder(s) dropped were skipped.",msgImageWidthSmall:'Width of image file "{name}" must be at least {size} px.',msgImageHeightSmall:'Height of image file "{name}" must be at least {size} px.',msgImageWidthLarge:'Width of image file "{name}" cannot exceed {size} px.',msgImageHeightLarge:'Height of image file "{name}" cannot exceed {size} px.',msgImageResizeError:"Could not get the image dimensions to resize.",msgImageResizeException:"Error while resizing the image.<pre>{errors}</pre>",dropZoneTitle:"Drag & drop files here &hellip;"},e.extend(e.fn.fileinput.defaults,e.fn.fileinputLocales.en),e.fn.fileinput.Constructor=Y,e(document).ready(function(){var i=e("input.file[type=file]");i.length&&i.fileinput()})});
0 19 \ No newline at end of file
... ...
src/main/webapp/static/assets/plugins/fileinput/fileinput_locale_zh.js 0 → 100644
  1 +/*!
  2 + * FileInput Chinese Translations
  3 + *
  4 + * This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or
  5 + * any HTML markup tags in the messages must not be converted or translated.
  6 + *
  7 + * @see http://github.com/kartik-v/bootstrap-fileinput
  8 + * @author kangqf <kangqingfei@gmail.com>
  9 + *
  10 + * NOTE: this file must be saved in UTF-8 encoding.
  11 + */
  12 +(function ($) {
  13 + "use strict";
  14 +
  15 + $.fn.fileinputLocales['zh'] = {
  16 + fileSingle: '文件',
  17 + filePlural: '多个文件',
  18 + browseLabel: '选择 &hellip;',
  19 + removeLabel: '移除',
  20 + removeTitle: '清除选中文件',
  21 + cancelLabel: '取消',
  22 + cancelTitle: '取消进行中的上传',
  23 + uploadLabel: '上传',
  24 + uploadTitle: '上传选中文件',
  25 + msgZoomTitle: '查看详情',
  26 + msgZoomModalHeading: '详细预览',
  27 + msgSizeTooLarge: '文件 "{name}" (<b>{size} KB</b>) 超过了允许大小 <b>{maxSize} KB</b>.',
  28 + msgFilesTooLess: '你必须选择最少 <b>{n}</b> {files} 来上传. ',
  29 + msgFilesTooMany: '选择的上传文件个数 <b>({n})</b> 超出最大文件的限制个数 <b>{m}</b>.',
  30 + msgFileNotFound: '文件 "{name}" 未找到!',
  31 + msgFileSecured: '安全限制,为了防止读取文件 "{name}".',
  32 + msgFileNotReadable: '文件 "{name}" 不可读.',
  33 + msgFilePreviewAborted: '取消 "{name}" 的预览.',
  34 + msgFilePreviewError: '读取 "{name}" 时出现了一个错误.',
  35 + msgInvalidFileType: '不正确的类型 "{name}". 只支持 "{types}" 类型的文件.',
  36 + msgInvalidFileExtension: '不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.',
  37 + msgUploadAborted: '该文件上传被中止',
  38 + msgValidationError: '文件上传错误',
  39 + msgLoading: '加载第 {index} 文件 共 {files} &hellip;',
  40 + msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',
  41 + msgSelected: '{n} {files} 选中',
  42 + msgFoldersNotAllowed: '只支持拖拽文件! 跳过 {n} 拖拽的文件夹.',
  43 + msgImageWidthSmall: '宽度的图像文件的"{name}"的必须是至少{size}像素.',
  44 + msgImageHeightSmall: '图像文件的"{name}"的高度必须至少为{size}像素.',
  45 + msgImageWidthLarge: '宽度的图像文件"{name}"不能超过{size}像素.',
  46 + msgImageHeightLarge: '图像文件"{name}"的高度不能超过{size}像素.',
  47 + msgImageResizeError: '无法获取的图像尺寸调整。',
  48 + msgImageResizeException: '错误而调整图像大小。<pre>{errors}</pre>',
  49 + dropZoneTitle: '拖拽文件到这里 &hellip;',
  50 + slugCallback: function(text) {
  51 + return text ? text.split(/(\\|\/)/g).pop().replace(/[^\w\u4e00-\u9fa5\-.\\\/ ]+/g, '') : '';
  52 + },
  53 + fileActionSettings: {
  54 + removeTitle: '删除文件',
  55 + uploadTitle: '上传文件',
  56 + indicatorNewTitle: '没有上传',
  57 + indicatorSuccessTitle: '上传',
  58 + indicatorErrorTitle: '上传错误',
  59 + indicatorLoadingTitle: '上传 ...'
  60 + }
  61 + };
  62 +})(window.jQuery);
0 63 \ No newline at end of file
... ...
src/main/webapp/static/assets/ueditor/dialogs/anchor/anchor.html 0 → 100644
  1 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2 + "http://www.w3.org/TR/html4/loose.dtd">
  3 +<html>
  4 + <head>
  5 + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  6 + <title></title>
  7 + <style type="text/css">
  8 + *{color: #838383;margin: 0;padding: 0}
  9 + html,body {font-size: 12px;overflow: hidden; }
  10 + .content{padding:5px 0 0 15px;}
  11 + input{width:210px;height:21px;line-height:21px;margin-left: 4px;}
  12 + </style>
  13 + </head>
  14 + <body>
  15 + <div class="content">
  16 + <span><var id="lang_input_anchorName"></var></span><input id="anchorName" value="" />
  17 + </div>
  18 + <script type="text/javascript" src="../internal.js"></script>
  19 + <script type="text/javascript">
  20 + var anchorInput = $G('anchorName'),
  21 + node = editor.selection.getRange().getClosedNode();
  22 + if(node && node.tagName == 'IMG' && (node = node.getAttribute('anchorname'))){
  23 + anchorInput.value = node;
  24 + }
  25 + anchorInput.onkeydown = function(evt){
  26 + evt = evt || window.event;
  27 + if(evt.keyCode == 13){
  28 + editor.execCommand('anchor', anchorInput.value);
  29 + dialog.close();
  30 + domUtils.preventDefault(evt)
  31 + }
  32 + };
  33 + dialog.onok = function (){
  34 + editor.execCommand('anchor', anchorInput.value);
  35 + dialog.close();
  36 + };
  37 + $focus(anchorInput);
  38 + </script>
  39 + </body>
  40 +</html>
0 41 \ No newline at end of file
... ...